使用Spring的KeyHolder和以编程方式生成的主键

sma*_*sma 8 spring primary-key oracle10g spring-jdbc jdbctemplate

我使用Spring的NamedParameterJdbcTemplate来执行对表的插入.该表在序列上使用NEXTVAL来获取主键.然后,我希望将生成的ID传回给我.我正在使用Spring的KeyHolder实现,如下所示:

KeyHolder key = new GeneratedKeyHolder();
jdbcTemplate.update(Constants.INSERT_ORDER_STATEMENT, params, key);
Run Code Online (Sandbox Code Playgroud)

但是,当我运行此声明时,我得到:

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)
Run Code Online (Sandbox Code Playgroud)

我缺少什么想法?

小智 19

刚刚解决了类似问题 - 使用Oracle需要使用其他方法(来自NamedParameterJdbcOperations) -

int update(String sql,
           SqlParameterSource paramSource,
           KeyHolder generatedKeyHolder,
           String[] keyColumnNames)
           throws DataAccessException
Run Code Online (Sandbox Code Playgroud)

使用包含自动生成列的keyColumnNames,在我的例子中只是["Id"].否则你得到的只是ROWID.有关详细信息,请参阅Spring doc

  • 感谢这个问题比以前的答案更好地回答,也解决了我的问题 (2认同)

sup*_*ova 5

没有详细说明@konstantin的答案:这是一个完整的工作示例:假设数据库是Oracle,并且存储生成的ID的列名称是“GENERATED_ID”(可以是任何名称)。注意:在此示例中,我使用的是 NamedParameterJdbcTemplate.update(....) ,而不是 Spring 的 JdbcTemplate 类。

       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 )
                {
        }
        }
Run Code Online (Sandbox Code Playgroud)


ska*_*man -4

我认为您使用了错误的方法JdbcTemplate。唯一与update您的代码片段匹配的方法是

int update(String sql, Object... args)
Run Code Online (Sandbox Code Playgroud)

如果是这样,您将paramsandkey作为一个两元素 vargs 数组传递,并将JdbcTemplatekey视为正常的绑定参数,并错误地解释它。

唯一需要 aupdate的公共方法是JdbcTemplateKeyHolder

int update(PreparedStatementCreator psc, KeyHolder generatedKeyHolder)
Run Code Online (Sandbox Code Playgroud)

因此,您需要重新编写代码才能使用它。

  • 误导性的,请检查康斯坦丁的以下答案 (3认同)