当我清理一些代码时,FindBugs 向我指出了一些使用 Connection、CallableStatement 和 ResultSet 对象的 JDBC 代码。这是该代码的一个片段:
CallableStatement cStmt = getConnection().prepareCall("...");
...
ResultSet rs = cStmt.executeQuery();
while ( rs.next() )
{
...
}
cStmt.close();
rs.close();
con.close();
FindBugs 指出这些应该位于finally 块内。我开始重构我的代码来做到这一点,并且我开始想知道如何处理finally块中的代码。
创建 Connection 对象的 CallableStatement 可能会引发异常,从而使我的 ResultSet 对象保留为 null。当我尝试关闭 ResultSet 时,我会收到 NullPointerException 异常,而我的 Connection 将永远不会关闭。的确,这个线程 https://stackoverflow.com/questions/2362686/how-to-correctly-close-resources提出了相同的概念,并表明将 close() 调用包装在空检查中是一个好主意。
但其他可能的例外情况又如何呢?根据 Java API 规范,“如果发生数据库错误”,Statement.close() 可以抛出 SQLException。因此,即使我的 CallableStatement 不为 null 并且我可以成功地对其调用 close(),我仍然可能会遇到异常并且没有机会关闭其他资源。
我能想到的唯一“故障安全”解决方案是将每个 close() 调用包装在自己的 try/catch 块中,如下所示:
finally {
try {
cStmt.close();
} catch (Exception e) { /* Intentionally Swallow Exception */ }
try {
rs.close();
} catch (Exception e) { /* Intentionally Swallow Exception */ }
try {
con.close();
} catch (Exception e) { /* Intentionally Swallow Exception */ }
}
男孩,如果这看起来不那么糟糕的话。有更好的方法来解决这个问题吗?
我认为最好的答案已经被提到了,但我认为提到您可以考虑自动关闭资源的新 JDK 7 功能可能会很有趣。
try{
try(Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/hrdb", "obiwan", "kenobi");
Statement stm = conn.createStatement();
ResultSet rs = stm.executeQuery("select name from department")) {
while(rs.next()){
System.out.println(rs.getString("name"));
}
}
}catch(SQLException e){
//you might wanna check e.getSuppressed() as well
//log, wrap, rethrow as desired.
}
现在并不是所有人都可以迁移到 JDK 7,但对于那些可以开始使用开发人员预览版的人来说,这提供了一种有趣的做事方式,并且肯定可能会在不久的将来弃用其他方法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)