postgresql - 用于多个准备好的语句的 JDBC 批处理
问题描述
是否可以将来自多个 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...
这些语句需要成为单个事务的一部分,我想在到服务器的一次往返中完成它们。
要在单次往返中发送它们,有两种选择:为每个命令创建一个 Statement 然后调用.addBatch()
,或者为每个命令创建一个PreparedStatement
,然后调用.setString()
,.setInt()
等等。对于参数值,然后调用.addBatch()
。
第一个选择的问题是在 . addBatch()
调用效率低下,并且您无法从已清理的参数输入中受益。
第二种选择的问题是它可能无法保留 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()
调用Statement
或PreparedStatement
对象时都会执行批处理。换句话说,这只执行与该语句对象的批处理相关联的语句(或值集)。不可能跨多个语句对象“排序”执行。在单个批次中,订单被保留。
如果您需要以特定顺序执行语句,则需要以该顺序显式执行它们。这要么意味着单独调用execute()
每个值集,要么使用单个Statement
对象并动态生成语句。由于 SQL 注入的可能性,不推荐使用最后一种方法。
推荐阅读
- docker - ingress 如何决定他是否必须在 http 或 https 上公开 kubernetes 服务?
- angular - ngx-charts 折线图持久背景
- php - 为什么没有定义错误Route [dataProcessing]?
- c++ - QT Image Viewer 示例,可能存在内存泄漏?
- reactjs - 如何在 React Hook 中使用节流阀或去抖动?
- sql - 计算 BACKLOG Y-1
- ios - iOS AVFoundation - 视频合并后缩放
- spring - 阿帕奇骆驼石英2
- css - Safari 和 Firefox 无法加载背景渐变
- php - 如何在 Yii fileField 中显示值(“路径”)?