Spring 管理環境でこの例外が発生する可能性は、トランザクションの伝播が次のように設定されている場合REQUIRED
です。
<tx:method name="do*" propagation="REQUIRED" />
次のようなシナリオを考えてみましょう:
Caller -------> [Transactional Method1(m1)] ----------> [Transactional Method2(m2)]
Spring が管理する環境では、トランザクションとの間に違いがlogical
あります。physical
このlogical
設定が適用されるメソッドごとに、トランザクション スコープが作成されます。methodのlogical
トランザクション スコープm1
が と異なりm2
ます。各logical
トランザクションは、独自のロールバックのみのステータスを個別に決定できます。また、この設定により、外側のトランザクション スコープ (m1 のスコープ) は、内側のトランザクション スコープ (m2 のスコープ) から論理的に独立しています。
ただし、これらのスコープはすべて同じphysical
トランザクションにマップされます。そのため、内側のトランザクションがロールバック対象としてマークされている場合、(外側のトランザクションから例外がスローされなくても) 外側のトランザクションがコミットされる可能性に影響します。
内部トランザクションからスローされた例外があり、ロールバックのマークが付けられている場合。ただし、外部トランザクションから例外がスローされないため、ロールバック自体が決定されていないため、ロールバック (内部トランザクション スコープによってサイレントにトリガーされる) は予期しないものです。そして、UnexpectedRollbackException
その時点で対応する がスローされます。
そのため、(外部の呼び出し元が認識していない) 内部トランザクションが暗黙的にトランザクションをロールバックのみとしてマークした場合、外部の呼び出し元はUnexpectedRollbackException
まだ commit を呼び出している場合に を受け取ります。これは、コミットの代わりにロールバックが実行されたことを外部の呼び出し元に示します。これは、例外が発生してトランザクションがロールバックされたことをトランザクションの呼び出し元に知らせるための予期された動作です。