6

JDBCStatementおよびを作成していますResultSet

closeFindbugsは、例外がスローされた場合にこれらを行わないことを正しく指摘しています。

だから今私は持っています:

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 を使用している場合は、事実のResultSet拡張AutoCloseableを利用して、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ようにおそらく使用します。

私の古いコードでは、私が使用した 2 つのアプローチがあります。

1 つ目は、次の形式の静的ヘルパー クラスのヘルパー メソッドのセットです。

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

2 番目のアプローチは、 を使用しLinkedList、開いた順序で物事を追加し、逆の順序でループして基本的に上記を実行するヘルパーを用意することでした。


いずれの場合も、閉じる必要がある 18 の異なる JDBC オブジェクトにならないように、メソッドを十分に短くするように努めています。(私は「努力する」と言います... 私は常に成功するとは限りません。)

于 2013-05-13T12:56:44.523 に答える
3

これを自分で書くのではなく、Apache Commons DbUtils.closeQuietly()を調べてください。

ResultSetsこれにより、Statementsとの組み合わせが閉じConnectionsられ、途中で null が処理されます。ResultSets複数の, noteは処理しませんが、それ以外の場合は便利です。

于 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 に答える