Domanda

Sto usando NamedParameterJdbcTemplate di primavera per eseguire un inserimento in una tabella. La tabella utilizza un NEXTVAL su una sequenza per ottenere la chiave primaria. Allora voglio questo ID generato da passare di nuovo me. Sto usando implementazione responsabile delle chiavi di primavera in questo modo:

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

Tuttavia, quando si esegue questa affermazione, sto ottenendo:

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)

Tutte le idee che mi manca?

È stato utile?

Soluzione

Penso che si sta utilizzando il metodo sbagliato su JdbcTemplate. L'unico uno dei metodi update che sembrerebbero per abbinare il vostro frammento di codice è

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

Se è così, si sta passando params e key come un elemento-due vargs array e JdbcTemplate sta trattando key come normali parametri legano, e mis-interpretazione.

Il metodo update unico pubblico sul JdbcTemplate che prende un KeyHolder è

int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder)

Quindi, è necessario riformulare il codice per utilizzare questo.

Altri suggerimenti

appena risolto un problema simile - con Oracle è necessario utilizzare un altro metodo (da NamedParameterJdbcOperations) -

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

con keyColumnNames contenenti colonne generate automaticamente, nel mio caso solo [ "Id"]. In caso contrario, tutto quello che ottiene è ROWID. Vedere Primavera doc per i dettagli.

Devi eseguire il JdbcTemplate.update(PreparedStatementCreator p, KeyHolder k).

La chiave restituita dal database verrà iniettato l'oggetto parametro KeyHolder.

Un esempio:

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);

Maggiori informazioni possono essere trovate qui nella documentazione di riferimento.

Non approfondisce risposta @konstantin: Ecco un esempio completamente funzionante: Supponendo Database Oracle e il nome della colonna che memorizzano generato Id è "GENERATED_ID" (può essere qualsiasi nome). NOTA: Ho usato NamedParameterJdbcTemplate.update (....) In questo esempio non JdbcTemplate classe di 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;
}
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top