java:在 H2 中的 executeBatch() 之后检索键

Posted

技术标签:

【中文标题】java:在 H2 中的 executeBatch() 之后检索键【英文标题】:java: retrieve keys after executeBatch() in H2 【发布时间】:2013-01-29 10:38:57 【问题描述】:

我正在尝试从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) 数据库。

【问题讨论】:

您使用的是哪个数据库/JDBC 驱动程序?应该是JDBC实现的问题。 只是为了创建完整的图片显示请rs迭代代码 @partlov 你是对的。部分 JDBC 实现不支持 getGeneratedKeys() 功能:***.com/questions/13641832/… 【参考方案1】:

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

返回一个包含最后生成的自动增量的结果集 此连接的密钥(如果有)。如果没有生成密钥 最后一个修改语句,则返回一个空的结果集。 返回的结果集只包含最后一行的数据。

【讨论】:

它不应该被认为是正常行为,而是限制。他们应该按照 JDBC 规范来实现这个,所以他们的驱动是不完整的。 从 1.4.191 版本开始支持。见:github.com/h2database/h2database/issues/156【参考方案2】:

您必须迭代 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();        

【讨论】:

谢谢。 getGeneratedKeys() 返回一个 ResultSet,所以迭代是必要的(这是我尝试的第一件事)。对不起,我没有在前面提到。我尝试了你的迭代,但它也没有工作。【参考方案3】:

这是 H2 实现的限制。这是issue。

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

【讨论】:

【参考方案4】:

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

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

例如选项(b)

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

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

【讨论】:

谢谢。我的实现非常简单,没有共享连接,只是一个带有嵌入文件的应用程序。

以上是关于java:在 H2 中的 executeBatch() 之后检索键的主要内容,如果未能解决你的问题,请参考以下文章

在executeBatch()之前如何检查Prepared Statement是不是有一些批次?

Java sql如何进行executeBatch()插入以返回布尔值

jdbc的executeBatch()返回正确的行计数

java对mysql进行批处理插入数据,如何返回错误的没插入数据

JDBC连接oracle executeBatch方法执行成功返回值-2

内存数据库中的 H2:使用 JDBC 设置时区? Java 单元测试