Springのトランザクション伝播動作:Spring 6/Boot 3の実務的な適用範囲
1. 伝播動作
- REQUIRED:トランザクションがあれば参加し、なければ新規作成します。
- REQUIRES_NEW:外側のトランザクションを中断し、独立したトランザクションを作成するため、接続を1つ余計に確保します。
- SUPPORTS:トランザクションがあれば参加し、なければトランザクションなしで実行できます。
- NOT_SUPPORTED:トランザクションを中断し、トランザクションなしで実行します。
- MANDATORY:既存のトランザクションが必要です。
- NEVER:トランザクションがすでに存在する場合は失敗します。
- NESTED:セーブポイントに対応したトランザクション内に、ネストされた境界を作成します。
2. 例
JAVA
@Service
public class OrderService {
@Transactional(rollbackFor = Exception.class)
public void create(Order order) {
repository.insert(order);
auditService.record(order.id());
}
}
@Service
public class AuditService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void record(long id) {
// 独立提交审计事务
}
}
3. トランザクションが反映されない場合
宣言的トランザクションはプロキシに依存しているため、this.innerMethod() はプロキシを迂回する可能性があります。そのほかには、Beanがnewで生成されている、例外が捕捉されている、チェック例外にrollbackForが設定されていない、別のスレッドから呼び出されている、データベースがトランザクションに対応していない、トランザクションマネージャーでエラーが起きている、といった原因が考えられます。まずはBeanを分割し、呼び出しがプロキシを経由するようにするのが優先です。
4. システムの境界
NESTEDは通常、同じ物理トランザクションとセーブポイントに依存します。REQUIRES_NEWは独立した物理トランザクションを使用します。Springのローカルトランザクションは、スレッド、MQ、HTTP、RPCをまたいで自動的に伝播しません。サービス間の処理には、信頼できるメッセージ、補償、TCC、Seataを使用してください。