7

我正在尝试从executeBatch()事务中检索生成的密钥,但我只获得要添加的最后一个密钥。

这是我的代码:

        PreparedStatement ps_insert = conn.prepareStatement(insertQuery, PreparedStatement.RETURN_GENERATED_KEYS);          
        for (int i = 0 ; i < adding_dates.length ; i++){
            ps_insert.setInt(1, Integer.parseInt(consultant_id));
            ps_insert.setDate(2, adding_dates[i]);
            ps_insert.setInt(3, Integer.parseInt(room_id));
            ps_insert.addBatch();
        }
        ps_insert.executeBatch();
        ResultSet rs = ps_insert.getGeneratedKeys(); //<-- Only the last key retrieved
        conn.commit();          

我究竟做错了什么?

编辑:抱歉没有提到我在嵌入式模式下使用 H2 ( http://www.h2database.com/html/main.html ) 数据库。

4

4 回答 4

3

根据 H2 jdbc driver javadocs,这是正常行为:

返回一个结果集,其中包含 为此连接最后生成的自动增量键(如果有)。如果最后一个修改语句没有生成任何键,则返回一个空结果集。返回的结果集仅包含最后一行的数据。

于 2013-01-29T10:51:51.537 回答
1

这是 H2 实施的限制。这是一个问题

现在使用不带批处理的插入/更新,或者通过选择以某种方式查询生成的键。

于 2013-01-29T10:59:06.000 回答
1

您必须迭代ResultSet以检索密钥。

  PreparedStatement ps_insert = conn.prepareStatement(insertQuery, PreparedStatement.RETURN_GENERATED_KEYS);          
    for (int i = 0 ; i < adding_dates.length ; i++){
        ps_insert.setInt(1, Integer.parseInt(consultant_id));
        ps_insert.setDate(2, adding_dates[i]);
        ps_insert.setInt(3, Integer.parseInt(room_id));
        ps_insert.addBatch();
    }
    ps_insert.executeBatch();
    ResultSet rs = ps_insert.getGeneratedKeys(); //<-- Only the last key retrieved

    if (rs.next()) {
       ResultSetMetaData rsmd = rs.getMetaData();
       int colCount = rsmd.getColumnCount();

       do {
           for (int i = 1; i <= colCount; i++) {
             String key = rs.getString(i);
             System.out.println("key " + i + "is " + key);
           }
       }
      while (rs.next();)
     } 

    conn.commit();        
于 2013-01-29T10:45:43.380 回答
0

如果您在 2 个线程之间共享会话/连接,并且其中两个线程尝试同时执行语句,那么您可能会看到这种问题。

您可能需要(a)使用连接池或(b)同步您对数据库的整个访问。

例如选项 (b)

在您的方法前面放置一个synchronize令牌以使其线程安全

只是一个想法,因为我不知道你完成了执行上下文

于 2013-01-29T10:46:15.133 回答