这是有效的代码:
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 id
结合使用,则 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
);
最佳答案
像这样的东西应该可以工作:
// 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
}
我认为(我不确定肯定!) key 是按照它们生成的顺序返回的。因此 ResultSet 的第一行应该映射到您正在处理的列表中的第一个“项目”。但请务必验证这一点!
编辑
如果这不起作用,请尝试指定为其生成值的实际列:
stmt = c.prepareStatement("INSERT ... ", new String[] {"id"});
关于java - 从postgresql中批量插入的行中检索序列号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16119257/