首页 > 解决方案 > JDBC getGeneratedKeys() 方法是否总是与插入元素的顺序相同

问题描述

我使用executeBatch()JDBC 插入多行,我想为另一个插入获取插入行的 id 我为此目的使用此代码:

insertInternalStatement = dbConncetion.prepareStatement(INSERT_RECORD, generatedColumns);

for (Foo foo: foosHashSet) {

    insertInternalStatement.setInt(1, foo.getMe());
    insertInternalStatement.setInt(1, foo.getMe2());
    // ..
    insertInternalStatement.addBatch();
}
insertInternalStatement.executeBatch();

// now get inserted ids
try (ResultSet generatedKeys = insertInternalStatement.getGeneratedKeys()) {

     Iterator<Foo> fooIterator= foosHashSet.iterator();
     while (generatedKeys.next() && fooIterator.hasNext()) {

         fooIterator.next().setId(generatedKeys.getLong(1));

     }
 }

它工作正常并返回 ID,我的问题是:

  1. 如果我迭代getGeneratedKeys()并且foosHashSetid 会以相同的顺序返回,以便从数据库返回的每个 id 都属于相应的 Foo 实例?

  2. 当我使用多线程和以上代码同时在多个线程中运行时怎么办?

  3. 有没有其他解决方案?我有两个表 foo1 和 foo2,我想先插入 foo1 记录,然后使用它们的主 id 作为 foo2 外键。

标签: javasqljdbc

解决方案


鉴于getGeneratedKeysJDBC 规范中未定义对批处理执行的支持,行为将取决于所使用的驱动程序。我希望任何支持生成的用于批处理执行的密钥的驱动程序都按添加到批处理中的顺序返回 ID。

但是,您使用 a 的事实Set是有问题的。大多数集合的迭代顺序没有定义,并且可以在迭代之间改变(通常只有在修改之后,但理论上你不能假设任何关于顺序的事情)。您需要使用具有保证顺序的东西,例如 aList或 a LinkedHashSet

在这里应用多线程可能是个坏主意:您一次只能使用来自单线程的 JDBC 连接。考虑多线程要么需要正确的锁定,要么需要您拆分工作负载以便它可以使用单独的连接。很难说这会改善还是恶化性能。


推荐阅读