Java Postgresql JDBC驱动程序中的批更新在自动提交中回滚

Java Postgresql JDBC驱动程序中的批更新在自动提交中回滚,java,postgresql,jdbc,batch-updates,Java,Postgresql,Jdbc,Batch Updates,我正在使用postgres 9.3-1100-jdbc41 JDBC4驱动程序进行批插入 根据JDBC规范,它的 到应用程序以禁用自动提交和提交,或 回滚事务 在我的例子中,我没有使用任何事务(即,auto-commit为true),但是如果批处理中的一个插入失败,仍然会回滚插入 根据JDBC规范,“如果批处理更新中的一个命令无法正确执行,此方法将抛出 BatchUpdateException,JDBC驱动程序可能继续处理,也可能不继续处理其余的命令 在批次中。”。这里并没有说以前执行的命令将回

我正在使用postgres 9.3-1100-jdbc41 JDBC4驱动程序进行批插入

根据JDBC规范,它的 到应用程序以禁用自动提交和提交,或 回滚事务

在我的例子中,我没有使用任何事务(即,auto-commit为true),但是如果批处理中的一个插入失败,仍然会回滚插入

根据JDBC规范,“如果批处理更新中的一个命令无法正确执行,此方法将抛出 BatchUpdateException,JDBC驱动程序可能继续处理,也可能不继续处理其余的命令 在批次中。”。这里并没有说以前执行的命令将回滚


我的理解错了吗?如果不是,为什么驱动程序会以这种方式运行,如果是,根据规范,什么是正确的行为。

据我所知,规范基本上将此留给驱动程序;如果批处理失败,它不会指定是否提交已处理的工作

PgJDBC在事务中执行批处理,因此如果批处理的任何部分失败,那么它将全部中止


如果您觉得这种行为不正确,那么您需要做的第一件事就是编写一个测试用例,证明其他驱动程序始终以不同的方式对PgJDBC进行操作,并将其提交给。我们没有时间研究其他驱动程序的行为,因此您需要编写测试用例并将其运行到其他一些流行的数据库(MS SQL Server、Oracle、DB2、MySQL等),或者安排其他人运行它。如果您显示PgJDBC的行为与其他驱动程序处理批处理的方式不同,那么值得考虑添加一个选项来更改该行为(并最终使其成为默认行为)。

如果您使用自动提交,如果我没有弄错的话,所有批处理插入仍然在单个事务中完成。可以将其视为编写一个插入多行(
insert-to..values(..),(..),(..),(..),(..)
)的插入的另一种方式。谢谢您的回复。但是规格呢。我认为这只是为了避免每次插入都通过网络往返,应用事务应该取决于应用程序。在db上,每个插入都应作为单个单元执行。作为一个用户,我可以在单个批次中添加不相关的插入,以避免往返,如果某些命令失败,则不应回滚。规范中说“可能继续处理,也可能不继续处理”-Postgres选择不继续。规范中说“可能继续处理,也可能不继续处理进一步的命令”我也发现了这个链接,但它太旧了,所以关于“可能无法继续”还有什么不清楚的?我认为你不能改变驱动程序的行为-毕竟Postgres本身不允许在一条语句失败时提交事务。这在Oracle中是不同的,在Oracle中,即使中间DML语句失败,您也可以提交事务。@a_horse_与_no_name在这种情况下,如果需要,可以更改驱动程序的行为
PreparedStatement
批处理(我假设这是关于这个问题的)作为一条
Parse
消息在线路上发送,然后是多条
Bind/Description/Execute
消息,每个批处理条目一条。如果一个事务尚未打开,则使用初始的
BEGIN
和finishing
COMMIT
打开一个事务。在自动提交中忽略包装事务描述语句,这样做很简单。@a_horse_和_no_名称不仅如此,而且v3协议行为符合规范的要求。如果语句中有错误,Pg将刷新流的其余部分,直到它遇到来自客户端的
Sync
消息。因此,我们不必担心在发生错误后阻止后续语句的执行-这是规范允许的,但在实践中是一个糟糕的想法。@a_horse_和_no_name,因此如果OP能够证明驾驶员当前行为不正确的令人信服的原因,我不认为这特别难以改变,除非我遗漏了什么地方。伙计们,我忘了提到,如果我们使用Statement.RETURN\u生成的\u键,成功的插入不会回滚。这件事使我更加困惑。