如何解决多个预处理语句的 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
,然后调用 {{ 1}}、.setString()
等用于参数值,然后调用 .setInt()
。
第一种选择的问题在于,在 ..addBatch()
调用中发送完整的 sql 字符串效率低下,而且您无法从经过清理的参数输入中获益。
第二种选择的问题在于它可能不保留 sql 语句的顺序。例如,
addBatch()
在上面的代码中,是否可以保证所有语句都按照我们调用的 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,?);");
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();
的顺序执行,即使是在不同的准备好的语句中?排序显然很重要;我们需要在插入新标签之前删除标签。
我还没有看到任何说明将为给定连接保留语句顺序的文档。
我正在使用 Postgres 和默认的 Postgres JDBC 驱动程序(如果有的话)。
解决方法
批处理是每个语句对象,因此每个 executeBatch()
调用对 Statement
或 PreparedStatement
对象执行一个批处理。换句话说,这仅执行与该语句对象的批处理关联的语句(或值集)。不可能跨多个语句对象“排序”执行。在单个批次中,订单被保留。
如果您需要按特定顺序执行语句,则需要按该顺序显式执行它们。这要么意味着对每个值集单独调用 execute()
,要么使用单个 Statement
对象并即时生成语句。由于 SQL 注入的可能性,不推荐使用最后一种方法。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。