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()插入以返回布尔值
java对mysql进行批处理插入数据,如何返回错误的没插入数据