9

这是有效的代码:

        Connection c = ds.getConnection();
        c.setAutoCommit(false);
        PreparedStatement stmt = c.prepareStatement("INSERT INTO items (name, description) VALUES(?, ?)");
        while (!(items = bus.take()).isEmpty()) {
          for (Item item : items) {
            stmt.setString(1, item.name);
            stmt.setString(2, item.description);
            stmt.addBatch();
          }
          stmt.executeBatch();
          c.commit();
        }

但现在我需要填充另一个表,其中 id 是外键。如果我将 INSERT 与RETURNING idthen一起使用,则executeBatch失败并出现“预期没有结果时返回结果”错误。

我看到了几种解决这个问题的方法

  • 进行单独插入而不是批量插入。
  • 用客户端生成的 guid 替换序列号。
  • 使用某种存储过程来执行批量插入并返回一个 id 列表。

在我看到的三种方法中,最后一种似乎保留了批量插入和返回 id 的效率,但它对我来说也是最复杂的,因为我从未编写过存储过程。

有没有更好的方法来批量插入和获取 ID?我使用 postgresql 特定的 API 而不是 jdbc 没有问题。

如果没有,任何人都可以画出这样一个存储过程吗?

这是表架构:

CREATE UNLOGGED TABLE items
(
  id serial,
  name character varying(1000),
  description character varying(10000)
)
WITH (
  OIDS=FALSE
);
4

1 回答 1

13

像这样的东西应该工作:

// tell the driver you want the generated keys
stmt =  c.prepareStatement("INSERT ... ", Statement.RETURN_GENERATED_KEYS);

stmt.executeBatch();

// now retrieve the generated keys
ResultSet rs = stmt.getGeneratedKeys();
while (rs.next()) {
 int id = rs.getInt(1);
 .. save the id somewhere or update the items list 
}

我认为(我不确定!)密钥是按照它们生成的顺序返回的。因此,ResultSet 中的第一行应该映射到您正在处理的列表中的第一个“项目”。但一定要验证!

编辑

如果这不起作用,请尝试指定为其生成值的实际列:

stmt =  c.prepareStatement("INSERT ... ", new String[] {"id"});
于 2013-04-20T10:52:47.170 回答