Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Spring's KeyHolder with programmatically-generated primary keys

I am using Spring's NamedParameterJdbcTemplate to perform an insert into a table. The table uses a NEXTVAL on a sequence to obtain the primary key. I then want this generated ID to be passed back to me. I am using Spring's KeyHolder implementation like this:

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

However, when I run this statement, I am getting:

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)

Any ideas what I am missing?

like image 316
sma Avatar asked May 12 '10 14:05

sma


People also ask

Where does the generatedkeyholder reside in Spring Boot?

The GeneratedKeyHolder resides in the spring-boot-starter-jdbc dependency. In the application.properties we turn off the banner and set the database driver. This is the SQL to create the users table. This is the User model. We have the MaritalStatus enumeration.

How to get auto-generated primary key IDs using jdbctemplate in spring JDBC?

Examples on how to get auto-generated primary key ids using JdbcTemplate and SimpleJdbcInsert in Spring Jdbc. 1. Getting Auto-Generated Key using JdbcTemplate 1.1. User Table 1.2. To retrieve auto-generated primery keys generated by database using JdbcTemplate, update () with PreparedStatementCreator is a convenient method.

What is generatedkeyholder in JDBC?

GeneratedKeyHolder is a standard implementation of the KeyHolder interface, which is used for holding auto-generated keys. The auto-generated keys are potentially returned by JDBC insert statements. In the following example we use the GeneratedKeyHolder to retrieve the Id of the created user.

Can I use primary keys instead of primitives in spring data JPA?

Most of the tutorials or blog posts that use Spring Data JPA use auto-generated primary keys. This post shows how you can use primary key objects instead of primitives like Long or UUID.


2 Answers

Just solved a similar issue - with Oracle you need to use another method (from NamedParameterJdbcOperations) -

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

with keyColumnNames containing auto-generated columns, in my case just ["Id"]. Otherwise all you get is ROWID. See Spring doc for details.

like image 110
Konstantin Avatar answered Oct 22 '22 23:10

Konstantin


You have to execute the JdbcTemplate.update(PreparedStatementCreator p, KeyHolder k).

The key returned from the database will be injected into the KeyHolder parameter object.

An example:

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

More information can be found here in the reference documentation.

like image 34
Espen Avatar answered Oct 22 '22 22:10

Espen