Using Spring's KeyHolder with programmatically-generated primary keys

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.


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.


No elaborate on @konstantin answer: Here is a fully working example: Assuming Database is Oracle and column name which store generated Id is "GENERATED_ID" ( Can be any name). NOTE: I used NamedParameterJdbcTemplate.update(....) In this example NOT JdbcTemplate class of 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 )
                {
        }
        }