我在清理一些代码时,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块内的代码。
可能CallableStatement或Connection对象的创建会引发异常,导致我的ResultSet对象为空。当我尝试关闭ResultSet时,我会得到NullPointerException,我的Connection也因此永远无法关闭。实际上,这个线程提出了同样的概念,并显示将close()调用包装在null检查中是一个好主意。
但其他可能的异常呢?根据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 */ }
}
哎呀,这看起来真是糟糕透顶。有没有更好的方法?