2012-02-13 10 views
35

接続の作成/受信、データベースへのクエリ、Java 7の自動リソース管理による結果処理の一般的なJDBCイディオムの統合方法、試用版-resourcesステートメント? (TutorialJava 7の自動リソース管理JDBC(リソース試行文)

のJava 7の前に、いつものパターンは、このようなものだった:これはConnectionを閉じてPreparedStatementます

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

    ... 
    con.commit(); 
} 

:あなたが行くことができるの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(); 
} 

ロールバックはどうですか?接続はtryブロック内でのみ使用可能であるため、ロールバックを含むcatch節を追加することはできません。

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

+1

これらの状況では、自動クローズは使用しません。この用語がすでに述べているように、それは単にリソースを閉じるためのものです。 Btw: 'try ...'ブロックの外側に接続を置くことは、接続が既に閉じられているのでtryブロックの後でロールバックできないので役に立ちません。 – home

+0

可能な複製http://stackoverflow.com/questions/8066501/how-should-i-use-try-with-resources-with-jdbc – Raedwald

+2

@Raedwald:これは複製ではありません。これはcon.rollback()に関するものです。 – Bijan

答えて

37
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 documentationによると、あなたは、通常のtryブロックとブロックのtry-と資源を組み合わせることができます。何も

  • うまくいかない場合は、何かが内側のブロックで問題が発生した場合にロールバック(何でされている)、PreparedStatementを閉じるには

    • 試み:IMO、上記の例では、正しい論理を、キャプチャ現在のトランザクション
    • 何も関係なく接続を終了しようとしました
    • 接続を閉じるときに何か問題が起きた場合、トランザクションをロールバックすることはできません(これは接続上のメソッドであり、現在は不確定な状態です)。試してみる

    Java 6以前では、tryブロック(try-finally外側、中間try-catch、内側try-finally)の3つのネストされたセットでこれを行います。 ARMシンタックスでは、このように簡潔になります。

  • +1

    あなたのソリューションは 'SQLException'をロールバックしますが、' RuntimeException'、 'Error'(など)には問題がありません。 'finally'ベースのコードはそうするでしょう。ルール "エラー'をキャッチしてはならない "は、エラーの場合にロールバックをオプションの操作にしません。 –

    +0

    @PiotrFindeisen:それを望むなら、 'SQLException'の代わりに' Throwable'をキャッチします。最後に、トランザクションが正しくロールバックされないことがあります。何か問題があるかどうかにかかわらずfinallyブロックがトリガーされるためです。あなたは確かにすべてがうまくいったらロールバックしたくありません! –

    +0

    はい、tryブロックを離れる前にコミットしない限り(成功した場合)。もちろん、その場合はコミット・アンド・ロールバックがありません。これは理想的ではありませんが、場合によってはロールバックが欠けている方が良いでしょう。私は答えを編集することをお勧めします。それはすべての例外を処理すべきコピーペーストコードです。 –

    3

    IMOでは、try-catchの外側にあるConnectionとPreparedStatementを宣言することが、この場合には最善の方法です。

    1

    あなたが取引にプールされた接続を使用する場合は、この方法でそれを使用する必要があります。

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

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

    関連する問題