web-dev-qa-db-ja.com

Java 7自動リソース管理JDBC(try-with-resourcesステートメント)

接続の作成/受信、データベースへのクエリ、そしておそらくJava 7の自動リソース管理、try-with-resourcesステートメントによる結果の処理)の一般的なJDBCイディオムを統合する方法( チュートリアル

Java 7の前は、通常のパターンは次のようなものでした:

Connection con = null;
PreparedStatement prep = null;

try{
    con = getConnection();
    prep = prep.prepareStatement("Update ...");
    ...
    con.commit();
}
catch (SQLException e){
    con.rollback(); 
    throw e;
}
finally{
    if (prep != null)
        prep.close();
    if (con != null)
        con.close();
}

Java 7を使用すると、次のことができます。

try(Connection con = getConnection(); PreparedStatement prep = con.prepareConnection("Update ..."){

   ...
   con.commit();
}

これはConnectionPreparedStatementを閉じますが、ロールバックはどうですか?接続はtryブロック内でしか使用できないため、ロールバックを含むcatch句を追加できません。

まだtryブロックの外で接続を定義していますか?ここで、特に接続プーリングが使用されている場合のベストプラクティスは何ですか?

37
TPete
try(Connection con = getConnection()) {
   try (PreparedStatement prep = con.prepareConnection("Update ...")) {
       //prep.doSomething();
       //...
       //etc
       con.commit();
   } catch (SQLException e) {
       //any other actions necessary on failure
       con.rollback();
       //consider a re-throw, throwing a wrapping exception, etc
   }
}

Oracleドキュメント によると、try-with-resourcesブロックを通常のtryブロックと組み合わせることができます。上記の例のIMOは、正しいロジックをキャプチャします。

  • 何も問題がなければ、PreparedStatementを閉じようとします
  • 内部ブロックで問題が発生した場合は、何が起こっていても、現在のトランザクションをロールバックします
  • 何があっても接続を閉じようとする
  • 接続のクローズで問題が発生した場合、トランザクションをロールバックすることはできません(これは接続のメソッドであり、現在は不確定な状態になっているため)。

Java 6およびそれ以前のバージョンでは、トライブロックを入れ子にして入れ子にしたセット(外側のトライファイナル、中間のトライキャッチ、内側のトライファイナル)でこれを行います。)ARM構文はこれをより簡潔にします。

40
Sean Reilly

IMO、try-catchの外部でConnectionおよびPreparedStatementを宣言することが、この場合に利用できる最良の方法です。

4
Garbage

トランザクションでプールされた接続を使用する場合は、次のように使用する必要があります。

_try (Connection conn = source.getConnection()) {
        conn.setAutoCommit(false);
        SQLException savedException = null;
        try {
            // Do things with connection in transaction here...
            conn.commit();
        } catch (SQLException ex) {
            savedException = ex;
            conn.rollback();
        } finally {
            conn.setAutoCommit(true);
            if(savedException != null) {
                throw savedException;
            }
        }
    } catch (SQLException ex1) {
        throw new DataManagerException(ex1);
    }
_

このサンプルコードは、自動コミット値の設定を処理します。

注、savedExceptionを使用すると、conn.rollback()が別の例外をスローした場合に備えて例外が保存されます。このように、最終的にブロックは「正しい」例外をスローします。

2
user3698328