トランザクションを「再生」する方法はありますか?つまり、RollbackExceptionが発生し、トランザクションがロールバックされることがあります。次に、トランザクションを「複製」して再試行できますか、またはロールバックが呼び出されると、トランザクションは失われますか?私は本当に変更が必要であり、後で再実行するためにすべての変更を追跡したくありません...
ありがとう、ウディ
トランザクションを「再生」する方法はありますか?つまり、RollbackExceptionが発生し、トランザクションがロールバックされることがあります。次に、トランザクションを「複製」して再試行できますか、またはロールバックが呼び出されると、トランザクションは失われますか?私は本当に変更が必要であり、後で再実行するためにすべての変更を追跡したくありません...
ありがとう、ウディ
それは、そのトランザクションがどこから来るかによって異なります。Java / JDBCでは、トランザクションは接続に関連付けられています。falseに設定setAutoCommit()
することから始めます(そうしないと、すべてのステートメントが独自の小さなトランザクションになります)。
トランザクションが失敗した後(つまり、ロールバックを呼び出した後)に接続を再利用することを妨げるものは何もありません。
Springを使用すると、事態はさらに複雑になります。Springはメソッドをトランザクションハンドラーでラップし、このハンドラーは、メソッドでスローされる例外から、現在のトランザクションで何をすべきかを推測しようとします。次の質問は、現在のトランザクションを作成したラッパーはどれですか?両方を呼び出すメソッドfoo()
を呼び出す場合がありました。bar()
@Transactional
bar()
からエラーをキャッチしfoo()
てDBに保存したかったのです。トランザクションが作成されたためfoo()
(Springが例外によって壊れたと考えたトランザクションにまだいたbar()
ため)、エラーを保存できなかったため、これは機能しませんでした。
解決策は、作成して作成しbaz()
、@Transactional(propagation=Propagation.REQUIRES_NEW)
から呼び出すことfoo()
でした。は、新しい新しいトランザクションを取得し、すでに(壊れた)トランザクションbaz()
があったDBから呼び出された場合でも、DBに書き込むことができます。foo()
もう1つの方法は、JDBCセーブポイントを使用して部分的にロールバックすることです。
そもそもなぜ例外が発生するのですか? これが問題の核心であるように私には思えます。
あなたは楽観的な文章に頼っていますか?その場合、(おそらく) バックオフと再試行回数を組み込んで、何らかの形式のループでデータベースの書き込みをラップする必要があります。残念ながら、これを自動的に行うことはできません (データベースの書き込みを再試行戦略でラップする何らかの形式のAOPソリューションを調査しない限り?)