我正在创建JDBC Statement
和ResultSet
s。
Findbugs正确地指出,如果抛出异常,我就不会close
这些。
所以现在我有:
Statement stmt = null;
ResultSet res = null;
try {
stmt = ...
res = stmt.executeQuery(...);
...
} finally {
try {
if(res != null)
res.close(); // <-- can throw SQLException
} finally {
if(stmt != null)
stmt.close();
}
}
(只有我有更多的结果集和准备好的陈述等等......所以我finally
s的嵌套更深一些)
必须有更好的方法来确保关闭大量结果集吗?
(旁白:在Symbian中,他们从不让析构函数/ close / release / remove -type方法抛出任何错误。我认为这是一个非常好的设计决策.Lin JDBC中的所有close
方法都可以抛出{{1在我看来,让事情变得不必要地复杂化。)
答案 0 :(得分:4)
如果您使用的是Java 7,那么您可以利用事实ResultSet
扩展AutoCloseable
并使用try-with-resources语句。
try (Statement sql = <WHATEVER>;
ResultsSet res = sql.executeQuery(<WHATEVER>)) {
// Use results
}
至少你可以避免使用finally
条款。
答案 1 :(得分:3)
在我可以依赖Java 7的代码中,我可能会使用try-with-resources
作为suggested by Duncan Jones。
在我的旧代码中,我使用了两种方法:
第一个是静态助手类上的一组辅助方法,形式如下:
public static final Statement quietClose(Statement s) {
if (s != null) {
try {
s.close();
}
catch (Exception e) {
// Do some useful logging here
}
}
return null;
}
然后在finally
区块中:
stmt = Helper.quietClose(stmt);
第二种方法是使用LinkedList
,按照我打开它们的顺序添加内容,然后有一个以相反顺序循环的帮助程序,基本上完成了上述操作。
在所有情况下,我都努力保持方法的简短,以至于我最终不需要关闭18个不同的JDBC对象。 (我说我“努力”......我并不总是成功。)
答案 2 :(得分:3)
不要自己写,请查看Apache Commons DbUtils.closeQuietly()。
这会关闭ResultSets
,Statements
和Connections
的组合,一路上处理空值。它不会处理多个ResultSets
,请注意,但不是很有用。
答案 3 :(得分:2)
A blog post by David M. Lloyd涵盖了这一点,探索了选项并确定了在创建的每个资源的正上方嵌套新try
/ finally
的模式。在我们的例子中,像这样:
Statement stmt = null;
ResultsSet res = null;
try {
stmt = ...
try {
res = stmt.executeQuery(...);
...
} finally {
try {
res.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
} finally {
try {
stmt.close();
} catch (Throwable t) {
t.printStackTrace();
}
}
如果你走这条路,最好还要遵循David的建议并创建一个可以在整个项目中使用的安全资源关闭方法。然后可以调用此方法来代替try
块中的catch
/ finally
块。
// put this anywhere you like in your common code.
public static void safeClose(Closeable c) {
try {
c.close();
} catch (Throwable t) {
// Resource close failed! There's only one thing we can do:
// Log the exception using your favorite logging framework
t.printStackTrace();
}
}
答案 4 :(得分:0)
要扩展reporter
建议的内容,请维护要关闭的元素列表。创建一个方法来执行捕获Throwable
的关闭并返回Throwable
。迭代列表收集返回的任何Throwables
并抛出返回的第一个。
private Throwable close(Closable c){
try{
c.cloase();
return null;
} catch (Throwable t){
return t;
};
}
private void workMethod(){
try{
}finally{
List<Throwable> ts = new ArrayList<Throwable>();
for(Closable c : closables){
Throwable T = close(c);
if (t != null)
ts.add(t);
}
if (!ts.isEmpty())
throw ts.get(0);
}
}