2009-09-01 20 views
2

メソッドconnection.rollback()をいつ呼び出す必要があるか教えてください。接続がすでにはautoCommit = falseのモードに設定されているCOS、上記のコードでconnection.rollback()メソッドはいつ呼び出す必要がありますか?

try{ 
    connection = getConnection(); 
    connection.setAutoCommit(false); 
    pstmt1 = connection.preparedstatement (...); 
    ... 
    pstt1.executeUpdate(); 
    pstmt2 = connection.preparedstatement (...); 
    ... 
    pstt2.executeUpdate(); 
    connection.commit(); 
}catch (Exception sqe) { sqe.printStacktrace(); 
}finally { 
    closeQuitely (pstmt1); 
    closeQuitely (pstmt2); 
    closeQuitely (connection); 
} 

我々はconnection.rollbackを()を使用していないが、いくつかの例外が発生した場合、その後もすべてが[私が推測する]正常に動作します。

したがって、このメソッドを使用する必要がある場合は、どのような状況になる可能性がありますか。この例も投稿してください。

+0

簡単な答え:プログラマは、rollback()またはcommit()を手動で呼び出すべきではありません。 – SteveD

+0

JDBCを学ぶこと、ライブラリ/フレームワークを書くこと、またはパフォーマンスに重大なことを行うことに加えて、JDBCやJPAなどのフレームワークを使ってトランザクションや接続を自動的に処理することはお勧めしません。インタラクションを取り締まるのは簡単すぎますし、膨大な量の定型コードがあります。 – SteveD

答えて

4

接続を閉じると、トランザクションは終了します。ほとんどのDBMSは、接続がどのような状況で終了したのかわからないため、トランザクションをロールバックします(おそらくあなたのプログラムは強制終了されましたか?)。すでにコミットしている場合、ロールバックは何も行いません。

一方、Connection-Poolingを使用している場合は、接続を閉じるとプールマネージャーがそれを傍受し、接続をロールバックして接続を開いたままにします。

catch節の内部、またはfinally節でもロールバックすることをお勧めします。一般に、コミット後に不必要なロールバックを行うことは害ではありません。

Postgresを使用している場合は、を開始する前にをロールバックして、トランザクションの開始時間を確実にリセットすることをお勧めします。これは、Postgresがcurrent_timestamp値をトランザクションが開始された時点まで保持していて、プールされた接続を使用している場合、これはずっと前のことでした。

+1

接続を閉じている特定のアプリケーションサーバーの接続プーリングの存在下で**トランザクションはロールバックされません**。これは、意図的なパフォーマンスの最適化です。つまり、接続の2回目のオープンは、実際には**同じ**接続を提供しますが、これは引き続きtrasnactionに関連付けられます。 – djna

4

例外を除いて、トランザクションは未解決です。最終的にタイムアウトになり、あなたが言うように、ロールバックされます。しかし、それまで(数分)、取引で取られたすべての錠が保持されます。接続は、あなたがコミットするつもりではないことに気付く方法がありません。そのような長期間にわたりロックを保持することは、並行性のために非常に後戻りです。

例外ケースにロールバックを追加します。

接続を閉じると、送信が終了するように見えることがあります。単純なJDBCを使用する場合、接続を閉じているアプリケーションサーバーに実装されている接続プールが存在する場合、「プールに戻る」という意味があります。および接続プールは現在のトランザクションとの接続を保持します。後でコード内で、依然として同じトランザクションの範囲内にある場合は、プールでと同じ接続を返す接続を要求します。これは本当にmoularアプリケーションを書くのに非常に便利ですが、接続をクローズするとトランザクションを解決できないというペナルティがあります。

begin tran 

// call a method 
    get connection 

    work 

    close connection 

// call another method 

    get connection // you get the **same** connection still associated with the tran 

    work 

    close connection 

commit 
+0

タイムアウトになりますか?私は静かに閉じて最終的に取引を破棄すると思います –

+0

はい、それはconnetionプールのpreseneceになります。私はこれを明確にしようとする答えを広げました – djna

0

コミットせずに接続を閉じると、トランザクションはロールバックされます。接続プールを使用している場合、それはおそらくあなたのためです。

例外が発生していないがまだコミットしたくない条件が発生した場合は、明示的なロールバックがおそらく適切です。

関連する問題