JDBC资源的正确使用方式
Posted
技术标签:
【中文标题】JDBC资源的正确使用方式【英文标题】:The correct way to use JDBC resources 【发布时间】:2014-04-17 16:07:44 【问题描述】:即使在 Java 7 中,我也经常看到这样的代码
Connection c = null;
PreparedStatement s = null;
try
c = dataSource.getConnection();
String sql = "insert into table (column1, column2) values (?, ?);
s = c.prepareStatement(sql);
int i = 1;
s.setString(i++, "111");
s.setString(i++, "222");
s.execute();
catch (SQLException e)
log.error("failed to insert", e);
finally
DbUtils.close(s, c); // closes s and c with no questions
但根据规范,当连接关闭时,所有语句和结果集都会被释放。
我听说 JDBC 驱动程序有可能不遵守 JDBC API 的规则,老方法更好。我的问题是听听对此的看法。代码看起来更好,但如果它很危险怎么办? 在我看来,最喜欢的方法是在此处使用 try-with-resources。够安全吗?
【问题讨论】:
“可以吗?”是个什么样的问题?你自己说过:“尝试资源”是更好的处理方式。 听说 JDBC 驱动程序有可能不按 JDBC API 的规则运行,老办法更好。我的问题是听听对此的看法。代码看起来更好,但如果它很危险怎么办? 嗯,这就是您应该在问题中提出的内容。 @FedorovMikhail '旧方法更好'?我认为这表明缺乏对 try-with-resources 工作原理的理解,因为从技术上讲,try-with-resources 可以完成您的代码所做的工作,除了较少的样板文件和实际异常反馈(如果出现任何问题)。 【参考方案1】:资源是程序完成后必须关闭的对象。因此您不必在finally
块中手动关闭对象
String sql = "insert into table (column1, column2) values (?, ?);
try(Connection c = dataSource.getConnection();
PreparedStatement s = c.prepareStatement(sql);)
int i = 1;
s.setString(i++, "111");
s.setString(i++, "222");
s.execute();
catch (SQLException e)
log.error("Failed to insert transaction", e);
【讨论】:
【参考方案2】:您应该始终释放/关闭您使用的资源,例如 ResultSet、Statement、Connection。这应该在 finally 块中完成。您在此处粘贴的 sn-p 看起来不错(只要 s 和 c 在 QuietDb 中关闭)。
【讨论】:
【参考方案3】:虽然closing a Connection
will close all Statement
s associated with it,但在大多数数据库中,您可以同时为任何一个Connection
打开多少Statement
s。
如果您不关闭Statement
s,则会增加ORA-01000: maximum open cursors exceeded
等错误的可能性。
如果您关闭Statements
、they also close their ResultSet
s,那么您不必同时关闭这两个。
【讨论】:
这是假设实现行为良好,但并非总是如此。完成后最好显式关闭资源。【参考方案4】:使用try-with-resources
,您的代码可以重写为:
try (
Connection c = dataSource.getConnection();
PreparedStatement s = c.prepareStatement("insert into table (column1, column2) values (?, ?)");
)
int i = 1;
s.setString(i++, "111");
s.setString(i++, "222");
s.execute();
catch (SQLException e)
log.error("failed to insert", e);
这保证了语句和连接都被关闭(即使关闭语句会引发异常!)。唯一的区别可能是关闭时可能会抛出异常,因为我不知道您的DbUtils.close
是否会吞下异常。
一般而言,try-with-resources 提供了更简洁的代码,并且更能确保资源以正确的顺序正确关闭,而无需太多样板。
【讨论】:
以上是关于JDBC资源的正确使用方式的主要内容,如果未能解决你的问题,请参考以下文章
Java避坑指南:finally块的陷阱及正确的关闭资源方式小
Java避坑指南:finally块的陷阱及正确的关闭资源方式小
Java避坑指南:finally块的陷阱及正确的关闭资源方式小