Frage

Ich verwende Spring NamedParameterJdbcTemplate einen Einsatz in eine Tabelle auszuführen. Die Tabelle verwendet eine NEXTVAL auf einer Sequenz, die die Primärschlüssel zu erhalten. Ich möchte dann diese erzeugte ID zu mir zurückgeleitet. Ich verwende Spring KEYHOLDER Umsetzung wie folgt aus:

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

Allerdings, wenn ich diese Anweisung ausführen, erhalte ich:

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)

Alle Ideen, was ich vermisst?

War es hilfreich?

Lösung

Ich glaube, Sie die falsche Methode auf JdbcTemplate verwenden. Der einzige, der update Methoden, die Code-Fragment erscheinen würde, ist entsprechen

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

Wenn ja, Sie vorbei params und key als Zwei Element vargs Array und JdbcTemplate ist key als normale binden Parameter behandelt und falsch interpretiert es.

Die einzige öffentliche update Methode auf JdbcTemplate, die eine KeyHolder nimmt, ist

int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder)

So müssen Sie Ihren Code neu zu formulieren, dass verwenden.

Andere Tipps

gelöst gerade ein ähnliches Problem - mit Oracle müssen Sie eine andere Methode verwenden (von NamedParameterJdbcOperations) -

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

mit keyColumnNames enthält, automatisch generierte Spalten, in meinem Fall nur [ "id"]. Ansonsten sind alle bekommen Sie ist ROWID. Siehe Frühling doc .

Sie haben die JdbcTemplate.update(PreparedStatementCreator p, KeyHolder k) auszuführen.

Der Schlüssel aus der Datenbank zurückgegeben wird in das KeyHolder Parameter Objekt injiziert werden.

Ein Beispiel:

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

Weitere Informationen finden Sie hier in der Referenzdokumentation.

Nein auf @konstantin Antwort erarbeiten: Hier ist ein voll funktionsfähiges Beispiel: Unter der Annahme, Datenbank ist Oracle und Spaltennamen, die Id erzeugt Store ist „GENERATED_ID“ (kann ein beliebiger Name sein). HINWEIS: Ich habe NamedParameterJdbcTemplate.update (....) In diesem Beispiel nicht JdbcTemplate Klasse von Spring

.
       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 )
                {
        }
        }

Mit 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;
}
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top