6

我正在创建 JDBCStatementResultSets。

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();
    }
}

(只有我有更多的结果集和准备好的语句等等打开......所以我的finallys 嵌套更深)

是否有更好的方法来确保关闭大量结果集?

(顺便说一句:在 Symbian 中,他们从不让 destructors/close/release/remove 类型的方法抛出任何错误。我认为这是一个非常好的设计决策。在我看来close,JDBC 中的所有方法都可以抛出SQLException使事情变得不必要的复杂。)

4

5 回答 5

4

如果您使用的是 Java 7,那么您可以利用事实ResultSetextendsAutoCloseable并使用try-with-resources语句。

try (Statement sql = <WHATEVER>;
     ResultsSet res = sql.executeQuery(<WHATEVER>)) {
     // Use results
}

至少你避免了这些finally条款。

于 2013-05-13T12:57:21.957 回答
3

在我可以依赖 Java 7 的代码中,我可能会按照 Duncan Jones 的try-with-resources建议使用

在我的旧代码中,我使用了两种方法:

第一个是静态助手类上的一组助手方法,形式如下:

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);

第二种方法是使用 a LinkedList,按照我打开它们的顺序添加东西,然后有一个帮助程序以相反的顺序循环并基本上完成上述操作。


在所有情况下,我都努力使方法保持足够短,以免最终需要关闭 18 个不同的 JDBC 对象。(我说我“努力”......我并不总是成功。)

于 2013-05-13T12:56:44.523 回答
3

与其自己编写,不如查看Apache Commons DbUtils.closeQuietly()

这将关闭 , 和 的组合ResultSetsStatements一路Connections处理空值。它不会处理多个ResultSets,注意,但在其他方面很有用。

于 2013-05-13T13:01:32.973 回答
2

几年前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块。catchfinally

// 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();
    }
}
于 2013-05-13T13:00:32.973 回答
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);
   }
}
于 2013-05-13T12:57:38.860 回答