如果抛出异常,请确保关闭对象

时间:2013-05-13 12:48:22

标签: java

我正在创建JDBC StatementResultSet 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在我看来,让事情变得不必要地复杂化。)

5 个答案:

答案 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()

这会关闭ResultSetsStatementsConnections的组合,一路上处理空值。它不会处理多个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);
   }
}