Springのトランザクション(@Transactional
)で指定可能な伝播属性(propagation)についてのメモです。
目次
@Transactionalとは
- サービスクラスやコントローラクラスに付与できるアノテーションです。
- クラスまたはメソッドに付与して、トランザクションの範囲を指定できます。
- クラスに付与した場合、そのクラス内のメソッドすべてに対して
@Transactional
指定したものと同じ効果となります。 - メソッドに付与した場合、そのメソッドの開始と終了がトランザクション範囲となります。
- クラスとメソッドに同時に付与した場合、個別に付与したメソッドについては、その付与した指定が優先されます。2023-06-22 更新
- クラスに付与した場合、そのクラス内のメソッドすべてに対して
@Transactional指定例
@Transactional(propagation = Propagation.REQUIRED) public class SomeService { public void method1() { // このメソッドはクラスレベルで設定された Propagation.REQUIRED を使用します } public void method2() { // このメソッドはクラスレベルで設定された Propagation.REQUIRED を使用します } @Transactional(propagation = Propagation.NEVER) public void method3() { // このメソッドはメソッドレベルで設定された Propagation.NEVER を使用します } }
伝播属性(propagation)とは
- @Transactionが付与されたサービスメソッドから、@Transactionが付与されたサービスメソッドを呼び出すような場合にそれぞれのトランザクションをどう扱うかを指定するオプションです。
- 以下、7種類あります。
1. REQUIRED
- 既存のトランザクションが存在する場合、それに参加します。
- 既存のトランザクションが存在しない場合、新たなトランザクションを開始します。
REQUIRED
がデフォルトの設定となります。省略した場合、こちらが指定されたものとなります。基本的な動きとしては、一つの大きなトランザクションになってゆくイメージです。
2. REQUIRES_NEW
- 常に新たなトランザクションを開始します。
- 既存のトランザクションが存在する場合、既存のトランザクションは一時的に中断(一時停止)されます。
REQUIRES_NEW
は、後から呼び出した処理が新たな別トランザクションとして実行され、その間、元のトランザクションは停止しているため、差し込みで処理させたい場合などに利用できそうです。
3. MANDATORY
- 既存のトランザクションに参加します。
- 既存のトランザクションが存在しない場合は例外をスローします。
MANDATORY
は既存のトランザクションがある前提なので、ないと例外となります。
4. NEVER
- トランザクションなしで実行します。
- 既存のトランザクションが存在する場合は例外をスローします。
NEVER
は既存のトランザクションがない前提なので、あると例外となります。
5. NOT_SUPPORTED
- トランザクションなしで実行します。
- 既存のトランザクションが存在する場合、既存のトランザクションは一時的に中断(一時停止)されます。
NOT_SUPPORTED
は、REQUIRES_NEW
の後から呼び出す処理がトランザクションを張っていないバージョンです。元のトランザクションは停止しているため、差し込みで処理させたい場合などに利用できそうです。
6. SUPPORTS
- 既存のトランザクションが存在する場合、それに参加します。
- 既存のトランザクションが存在しない場合、トランザクションなしで実行します。
SUPPORTS
は、既存に合わせる動作をします。あれば参加するし、なければトランザクション自体作成しません。
7. NESTED
- 既存のトランザクションが存在する場合、そのトランザクションにネストしたトランザクションを開始します。
- 既存のトランザクションが存在しない場合、新たなトランザクションを開始します。
NESTED
はちょっと複雑です。その名前の示す通り、トランザクションはネストして作成されます。ネストした子トランザクションは、それぞれで完全なトランザクションとして機能するため、コミットもロールバックも可能となります。
ただし、親トランザクションが最終的にコミットした場合に限り、子トランザクションで決定した反映内容が最終的に反映されます。
親トランザクションが最終的にロールバックした場合、子トランザクションでコミットしていたとしても、それらも合わせてロールバックされます。
伝播属性(propagation)のまとめ
- 以下、まとめです。
A. 既存トランザクションがある場合
# | 伝播属性 | 新 | 既存 | 備考 |
---|---|---|---|---|
1 | REQUIRED | 既存に参加 | ||
2 | REQUIRES_NEW | 新たに開始 | 一時停止 | |
3 | MANDATORY | 既存に参加 | ||
4 | NEVER | 例外スロー | 既存はない前提 | |
5 | NOT_SUPPORTED | なしで実行 | 一時停止 | |
6 | SUPPORTS | 既存に参加 | ||
7 | NESTED | 既存にネストしたトランザクション開始 |
B. 既存トランザクションがない場合
# | 伝播属性 | 新 | 既存 | 備考 |
---|---|---|---|---|
1 | REQUIRED | 新たに開始 | ||
2 | REQUIRES_NEW | 新たに開始 | ||
3 | MANDATORY | 例外スロー | 既存はある前提 | |
4 | NEVER | なしで実行 | ||
5 | NOT_SUPPORTED | なしで実行 | ||
6 | SUPPORTS | なしで実行 | ||
7 | NESTED | 新たに開始 |
参考
参照
参考サイト
- (はてなブログ) Spring Bootでトランザクション(@Transactional)の伝搬属性(propagation)を試す
- (Qiita) 【Java・SpringBoot】@Transactionの設定まとめ