使用Spring JDBCTemplate插入新记录后如何获取生成的ID?

4

我知道这是一个重复的问题,但其他页面上的解决方案对我不起作用。

我有一个Oracle数据库,我想获取插入记录的ID(主键),但我无法做到。以下是我的代码和错误信息。

org.springframework.dao.DataRetrievalFailureException: 生成的密钥不是受支持的数字类型。无法将[oracle.sql.ROWID]强制转换为[java.lang.Number]

String query = "INSERT INTO JOBS (USERNAME, CREATED_ON, STATUS, JOBTYPE, DATA) " + "VALUES (?, ?, ?, ?, ?)";

try {

 KeyHolder holder = new GeneratedKeyHolder();

 jdbcTemplate.update(new PreparedStatementCreator() {

  @Override
  public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
   PreparedStatement ps = con.prepareStatement(query, Statement.RETURN_GENERATED_KEYS);
   ps.setString(1, "username");
   ps.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
   ps.setString(3, "status");
   ps.setString(4, "jobtype");
   ps.setString(5, "job-data");

   return ps;
  }
 }, holder);
 System.out.println("Holder tostring: " + holder.toString());
 System.out.println("Ran an update statement and got generated key. Key = " + holder.getKey().intValue());
 System.out.println("Key: " + holder.getKey().longValue());
 return true;
} catch (DataAccessException e) {
 System.err.println("Exception thrown inserting record into table. Error: " + e.getMessage());
 e.printStackTrace();
}

当我以调试模式运行应用程序时,我发现 holder 变量 keyList 的值为:[{ROWID=AAAKy2AAAAALRgdAAD}],但我没有得到插入记录的 ID。
创建表格脚本如下:
CREATE TABLE JOBS (
    ID          INTEGER                 GENERATED ALWAYS AS IDENTITY(START WITH 1 INCREMENT BY 1),
    USERNAME    VARCHAR2(20)            NOT NULL,
    CREATEDON   TIMESTAMP               NOT NULL,
    STATUS      VARCHAR2(10)            NOT NULL,
    JOBTYPE     VARCHAR2(15)             NOT NULL,
    DATA        VARCHAR2(1000 CHAR)     NOT NULL,

    PRIMARY KEY(ID)
);

将ID从INTEGER更改为NUMBER,并且应该使用序列(sequence)来生成ID。我认为Oracle不使用INTEGER作为数据类型,除非您在数据库中自定义数据类型。 - logger
嗨@logger,我将我的Jobs表ID更改为Number,并删除了Generated Always...并创建了序列以生成ID,并在插入命令上创建触发器以添加插入命令的ID值。但仍然面临相同的问题。 - Gaurav
1个回答

6

当使用con.prepareStatement(query, Statement.RETURN_GENERATED_KEYS)时,Oracle JDBC驱动程序将不会返回id列的值,而是返回ROW_ID(一个伪列,用于标识特定行),以便让您自己检索该值。

从历史上看,Oracle驱动程序采用这种方式是因为早期的Oracle版本没有identity列。

相反,您应该使用:

con.prepareStatement(query, new String[] { "ID" });

这条指令告诉Oracle返回指定列的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接