Java 从postgresql中的批插入行检索序列id
以下是有效的代码:Java 从postgresql中的批插入行检索序列id,java,postgresql,jdbc,batch-file,Java,Postgresql,Jdbc,Batch File,以下是有效的代码: Connection c = ds.getConnection(); c.setAutoCommit(false); PreparedStatement stmt = c.prepareStatement("INSERT INTO items (name, description) VALUES(?, ?)"); while (!(items = bus.take()).isEmpty()) {
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与返回id
一起使用,则executeBatch
将失败,并出现“结果是在没有预期结果时返回的”错误
我有几种方法可以解决这个问题
- 单独插入而不是批量插入
- 用客户端生成的guid替换序列id
- 使用某种存储过程执行批插入并返回ID列表
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
}
我认为(我不确定)键是按生成顺序返回的。因此,ResultSet中的第一行应该映射到您正在处理的列表中的第一个“项”。但一定要证实这一点
编辑
如果不起作用,请尝试指定为其生成值的实际列:
stmt = c.prepareStatement("INSERT ... ", new String[] {"id"});
看看JDBC
getGeneratedKeys
方法。不过,我还没有专门针对批处理连接验证它。用wCTE同时填充这两个表怎么样?@JakubKania-什么是wCTE?你能举个例子吗?@标记一个可写的CTE,它可以让你像这样链接查询。看这里:这是9.1+功能。@标记有更新吗?@mark:准备语句时,需要告诉驱动程序返回这些值。请看我的编辑。好的,可以了。但还剩下一些东西。听起来您不确定第一行是否映射到第一个返回的id。上的文档也没有说明这一点。然而,这是一条至关重要的信息。如果没有这一保证,该功能将毫无用处。至少对postgresql来说,这是有保证的吗?@mark:正如我所说:我不知道。你需要自己测试一下。我已经测试过了,但什么也证明不了。它在我的开发环境中工作的事实并不能说明它是否能在生产环境中工作。我们需要一位postgresql大师的权威性回答。但是我相信你的回答就是答案。请看一下,我在邮件列表上问了这个问题。目前看来,订单显然没有得到保证。你是在玩火,你把一些代码建立在期望的基础上。