Java预处理语句获取生成的键在DB2中不起作用,但在mySQL中起作用?

mdfafbf1  于 2022-11-07  发布在  DB2
关注(0)|答案(2)|浏览(197)

我有一个非常简单的表,在MySQL和DB2中都有,名为STUDENTID(主键,自动递增)、FIRST_NAMELAST_NAMEAGE
表在两个数据库中被复制,因此它们在语法上应该是相同的。但是,我花了一整天的时间试图弄清楚为什么当我编写一个简单的Java程序插入数据库时,MySQL版本通过PreparedStatement.getGeneratedKeys()返回生成的键,而DB2版本不返回任何东西。
我的代码如下所示:

String sql = "INSERT INTO STUDENT (FIRST_NAME, LAST_NAME, AGE) VALUES ('Jacob', 'Eldy', 19)"

final Connection connection = getConnection(dataSource.get());

int[] insertedRows = null;
ResultSet rs = null;
PreparedStatement ps = null;
try {
    ps = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
    ps.addBatch();

    insertedRows = ps.executeBatch();

    rs = ps.getGeneratedKeys();

    while(rs.next()) {
        LOGGER.info(rs.getString(1));
    }
    connection.commit();
} catch (Exception e) {
    try {
        connection.rollback();
    } catch (SQLException e) {
        e.printStackTrace();
    }

} finally {
    close(ps, connection);
}

在提交DB2和MySQL数据库的连接后,实际上都显示了插入的行,插入的行越多,就会出现一个新行,并带有自动递增的ID,但是只有MySQL数据库的值为while(rs.next()),DB2版本跳过了它,因为它是空的。
我做错了什么吗?这只是一个与DB2的不兼容问题,它只是不返回生成的值吗?如果是这样,解决这个问题的最佳解决方案是什么?
UPDATE,添加用于DB2和mySQL的两个DDL:
mySQL数据描述语言:

CREATE TABLE 'STUDENT'
  ...
  `ID` int NOT NULL AUTO_INCREMENT
  PRIMARY KEY('ID')
  AUTO_INCREMENT=19073

DB2数据库描述语言:

CREATE TABLE STUDENT
(
  ID INTEGER DEFAULT IDENTITY GENERATED ALWAYS NOT NULL
  PRIMARY KEY (ID)
)
xmq68pz9

xmq68pz91#

CREATE TABLE STUDENT 
(
  ID            INT NOT NULL GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
, FIRST_NAME    VARCHAR (20)
, LAST_NAME     VARCHAR (20)
, AGE           SMALLINT
);

以下代码基于其他人提供的Making batch updates in JDBC applications链接(此链接用于Db2 for LUW),可与上述表定义一起正常工作:

PreparedStatement ps = con.prepareStatement
          ( 
            "INSERT INTO STUDENT (FIRST_NAME, LAST_NAME, AGE) " +
            "VALUES (?,?,?)"
          , Statement.RETURN_GENERATED_KEYS
          );
          ps.setString (1, "Jacob"); 
          ps.setString (2, "Eldy");
          ps.setShort (3, (short) 19);
          ps.addBatch(); 
          ps.setString (1, "Jacob"); 
          ps.setString (2, "Eldy");
          ps.setShort (3, (short) 19);
          ps.addBatch();                                  

          int [] numUpdates = ps.executeBatch(); 

          for (int i=0; i < numUpdates.length; i++) 
            if (numUpdates[i] == Statement.SUCCESS_NO_INFO)
              System.out.println("Execution " + i + ": unknown number of rows updated");
            else
              System.out.println("Execution " + i + " successful: " + numUpdates[i] + " rows updated");
          ResultSet[] resultList = ((com.ibm.db2.jcc.DB2PreparedStatement) ps).getDBGeneratedKeys(); 
          if (resultList.length != 0) 
            for (int i = 0; i < resultList.length; i++) 
            {
                while (resultList[i].next()) 
                  System.out.println("Automatically generated key value = " + resultList[i].getBigDecimal(1));
                resultList[i].close();
            }
          else
            System.out.println("Error retrieving automatically generated keys");
dtcbnfnu

dtcbnfnu2#

我做错了什么吗?这只是一个与DB2的不兼容问题,它只是不返回生成的值吗?如果是这样,解决这个问题的最佳解决方案是什么?
是的,你做错了。这不是不兼容的问题,也不是一个问题。DB2不同于MySQL。你不能同时处理这两个,因为你有不兼容的DDL。因为没有记录插入DB2,所以键的值不可用。
此问题的解决方案是在插入记录时创建一个触发器,以确保将主键插入到数据库中。如果缺少一个键,则从序列中选择它并替换值。
现在,如果像这样将标识生成到DB2中

CREATE TABLE STUDENT
(
  ID INTEGER DEFAULT IDENTITY GENERATED ALWAYS NOT NULL
  PRIMARY KEY (ID)
)

因此,它将始终返回getGeneratedKeys()

相关问题