Pregunta

Estoy utilizando NamedParameterJdbcTemplate de primavera para realizar una inserción en una tabla. La tabla utiliza un NEXTVAL en una secuencia para obtener la clave principal. entonces yo quiero esto ID generado que se pasa de nuevo a mí. Estoy utilizando la aplicación de llaves de primavera de la siguiente manera:

KeyHolder key = new GeneratedKeyHolder();
jdbcTemplate.update(Constants.INSERT_ORDER_STATEMENT, params, key);

Sin embargo, cuando corro esta declaración, me estoy haciendo:

org.springframework.dao.DataRetrievalFailureException: The generated key is not of a supported numeric type. Unable to cast [oracle.sql.ROWID] to [java.lang.Number]
    at org.springframework.jdbc.support.GeneratedKeyHolder.getKey(GeneratedKeyHolder.java:73)

Cualquier idea lo que me falta?

¿Fue útil?

Solución

creo que estás usando el método equivocado en JdbcTemplate. El único de los métodos update que parecerían coincidir con su fragmento de código es

int update(String sql, Object... args)

Si es así, estás pasando params y key como de dos elementos vargs matriz y JdbcTemplate está tratando key como parámetros normales se unen, y la mala interpretación de la misma.

El método update única pública en JdbcTemplate que toma un KeyHolder es

int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder)

Por lo que usted necesita para reformular el código para utilizar eso.

Otros consejos

Sólo resolvió un problema similar - con Oracle Usted necesidad de utilizar otro método (de NamedParameterJdbcOperations) -

int update(String sql,
           SqlParameterSource paramSource,
           KeyHolder generatedKeyHolder,
           String[] keyColumnNames)
           throws DataAccessException

con keyColumnNames que contienen columnas generadas automáticamente, en mi caso solo [ "id"]. De lo contrario, lo único que consigue es ROWID. Ver Spring doc para más detalles.

Hay que ejecutar el JdbcTemplate.update(PreparedStatementCreator p, KeyHolder k).

La clave de regresar de la base de datos se inyecta en el objeto de parámetro KeyHolder.

Un ejemplo:

final String INSERT_ORDER_STATEMENT 
       = "insert into order (product_id, quantity) values(?, ?)";

KeyHolder keyHolder = new GeneratedKeyHolder();
    jdbcTemplate.update(new PreparedStatementCreator() {
        public PreparedStatement createPreparedStatement(
            Connection connection) throws SQLException {
                PreparedStatement ps = connection.prepareStatement(
                    INSERT_ORDER_STATEMENT, new String[] { "id" });
                ps.setInt(1, order.getProductId());
                ps.setInt(2, order.getQuantity());
                return ps;
            }
        }, keyHolder);

Más información se puede encontrar aquí en la documentación de referencia.

No dio detalles sobre la respuesta @konstantin: Este es un ejemplo completamente de trabajo: Suponiendo base de datos es Oracle y nombre de la columna que almacenan generado Id es "GENERATED_ID" (puede ser cualquier nombre). NOTA: He utilizado NamedParameterJdbcTemplate.update (....) En este ejemplo NO clase JdbcTemplate de la primavera

.
       public Integer insertRecordReturnGeneratedId(final MyObject obj)
            {
            final String INSERT_QUERY = "INSERT INTO MY_TABLE  VALUES(GENERATED_ID_SEQ.NEXTVAL, :param1, :param2)";
            try
                {
                    MapSqlParameterSource parameters = new MapSqlParameterSource().addValue( "param1", obj.getField1() ).addValue( "param2",  obj.getField1() ) ;
                    final KeyHolder holder = new GeneratedKeyHolder();
                    this.namedParameterJdbcTemplate.update( INSERT_QUERY, parameters, holder, new String[] {"GENERATED_ID" } );
                    Number generatedId = holder.getKey();
                   // Note: USING holder.getKey("GENERATED_ID") IS ok TOO.
                    return generatedId.intValue();
                }
                catch( DataAccessException dataAccessException )
                {
        }
        }

Con MySQL

CREATE TABLE `vets` (
  `id` int(4) unsigned NOT NULL AUTO_INCREMENT,
  `first_name` varchar(30) DEFAULT NULL,
  `last_name` varchar(30) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `last_name` (`last_name`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;


public @Data class Vet {
    private int id;
    private String firstname;
    private String lastname;
}

@Repository
public class VetDaoImpl implements VetDao {
/** Logger. */
private static final Logger LOGGER = LoggerFactory.getLogger(VetDaoImpl.class);

private static final String INSERT_VET = "INSERT INTO vets (first_name, last_name) VALUES (:first_name, :last_name)";

@Autowired
private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

@Override
public Number insertVet(final Vet vet) {
    MapSqlParameterSource paramSource = new MapSqlParameterSource();
    paramSource.addValue("first_name", vet.getFirstname());
    paramSource.addValue("last_name", vet.getLastname());
    KeyHolder keyHolder = new GeneratedKeyHolder();
    int nbRecord = namedParameterJdbcTemplate.update(INSERT_VET, paramSource, keyHolder, new String[] {"id" });
    LOGGER.info("insertVet: id ["+keyHolder.getKey()+"]");
    return nbRecord;
}
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top