【Spring】Springのトランザクション管理はFILOなので、後から開始したトランザクションから先に確定させる
どちゃくそハマったので、メモ。
★今回問題となったコード
Springにて、同一のサービス内で複数のDBにアクセス/ランザクション制御を行う必要があった。
複数のトランザクションを扱うため、@Transactional ではなく、PlatformTransactionManager を利用するようにした。
実装イメージとしては以下のような感じ。
code:java
@Service
public class HogeService {
@Autowired
private PlatformTransactionManager primary;
@Autowired
@Qualifier("secondaryTransactionManager")
private PlatformTransactionManager secondary;
public void execute(HogeServiceRequest request) {
// トランザクション開始
TransactionStatus pStatus = this.primary.getTransaction(new DefaultTransactionDefinition());
TransactionStatus sStatus = this.secondary.getTransaction(new DefaultTransactionDefinition());
try {
// do somthing.
// 正常終了すればコミット
this.primary.commit(pStatus);
this.secondary.commit(sStatus);
} catch (Exception e) {
// エラーが発生した場合はロールバック
this.primary.rollback(pStatus);
this.secondary.rollback(sStatus);
}
}
}
ここで、コミット時に以下のようなエラーが発生した。
code:bash
java.lang.IllegalStateException: Transaction synchronization is not active
なんか、トランザクションの同期がとれてねーよと言われている。
解決方法
Springのトランザクションは、FILO(スタック方式)で管理されている。(Springに限らず、どのFWでもそうだと思うが)
そのため、トランザクションの開始とは逆の順番でトランザクションを確定させる必要がある。
具体的にはコミット/ロールバックの操作は
×:primary -> secondary
〇 : secondary -> primary
に変更する必要がある。