Postgresql 多个准备语句的JDBC批处理

Postgresql 多个准备语句的JDBC批处理,postgresql,jdbc,prepared-statement,Postgresql,Jdbc,Prepared Statement,是否可以将多个JDBC准备语句中的提交批处理在一起 在我的应用程序中,用户将插入一条或多条记录以及相关表中的记录。例如,我们需要更新“contacts”表中的记录,删除“tags”表中的相关记录,然后插入一组新的标记 UPDATE contacts SET name=? WHERE contact_id=?; DELETE FROM tags WHERE contact_id=?; INSERT INTO tags (contact_id,tag) values (?,?); // insert

是否可以将多个JDBC准备语句中的提交批处理在一起

在我的应用程序中,用户将插入一条或多条记录以及相关表中的记录。例如,我们需要更新“contacts”表中的记录,删除“tags”表中的相关记录,然后插入一组新的标记

UPDATE contacts SET name=? WHERE contact_id=?;
DELETE FROM tags WHERE contact_id=?;
INSERT INTO tags (contact_id,tag) values (?,?);
// insert more tags as needed here...
这些语句需要是单个事务的一部分,我希望在到服务器的一次往返中完成它们

要在一次往返中发送它们,有两种选择:为每个命令创建一条语句,然后调用
.addBatch()
,或为每个命令创建一条
PreparedStatement
,然后调用
.setString()
.setInt()
等。对于参数值,然后调用
.addBatch()

第一种选择的问题是,在.addBatch()调用中发送完整的SQL字符串效率低下,而且您无法获得经过净化的参数输入的好处

第二种选择的问题是它可能无法保持SQL语句的顺序。比如说,

Connection con = ...;
PreparedStatement updateState = con.prepareStatement("UPDATE contacts SET name=? WHERE contact_id=?;");
PreparedStatement deleteState = con.prepareStatement("DELETE FROM contacts WHERE contact_id=?;");
PreparedStatement insertState = con.prepareStatement("INSERT INTO tags (contact_id,tag) values (?,?);");

updateState.setString(1, "Bob");
updateState.setInt(1, 123);
updateState.addBatch();

deleteState.setInt(1, 123);
deleteState.addBatch();

... etc ...
... now add more parameters to updateState, and addBatch()...
... repeat ...

con.commit();
在上面的代码中,是否可以保证所有语句都将按照我们称为
.addBatch()
的顺序执行,即使是在不同的准备语句之间?排序显然很重要;我们需要先删除标签,然后再插入新标签

我还没有看到任何文档说明将为给定的连接保留语句的顺序


我使用的是Postgres和默认的Postgres JDBC驱动程序,如果这很重要的话。

批处理是针对每个语句对象的,因此批处理是根据
executeBatch()
调用
语句或
PreparedStatement
对象执行的。换句话说,这只执行与该语句对象的批处理相关联的语句(或值集)。不可能跨多个语句对象“排序”执行。在单个批次中,订单将保留


如果需要按特定顺序执行语句,则需要按该顺序显式执行它们。这意味着对每个值集分别调用
execute()
,或者使用单个
语句
对象并动态生成语句。由于SQL注入的潜力,不推荐最后一种方法。

您永远不会在一次往返中完成所有这一切,因为提交本身,更不用说驱动程序在与数据库通信时所做的任何事情了,您对此一无所知,更不用说TCP在分段和确认段时所做的事情了。不管你怎么想,在任何情况下,一次往返都没有什么特别的好处。但是你在这里有一个严重的误解。在调用
executeBatch()
之前,批处理中实际上不会发生任何事情。然后这一切都会发生,而且是按顺序发生的,但是您必须按照您定义的顺序对所有三个
PreparedStatement
对象调用
executeBatch()
:比如
updateState.executeBatch();删除状态;executeBatch();insertState.executeBatch();首先进行所有更新,然后进行所有删除,然后进行所有插入。这是没有办法的。(当然,在提交之前,这一切都不会发生。)@user207421如果有多个子表(在我的例子中是7个,但会有更多),那么往返会产生很大的不同。假设每次往返的延迟为5毫秒,那么我们将每个父记录的延迟从5毫秒提高到35毫秒。如果你试图批量处理100条父记录,这是一件大事。局域网内的延迟是微不足道的。我到世界另一边的ping时间是8毫秒。您应该关注数据库操作的速度,它要长几个数量级:而不是像这样的琐事。尤其是不可实现的琐事。但很难理解为什么要更新要删除的行。