Spring Bootを使うと、利用技術に対応したPlatformTransactionManager
インタフェースの実装クラス(DataSourceTransactionManager
, JpaTransactionManager
, JtaTransactionManager
, etc...)のBean定義が自動で行われます。デフォのまま使えるか?というとちょっと微妙で、いくつかカスタマイズした方がよいパラメータがあると私は思っています。そんなこんなで・・・今回は、Spring Boot上でのPlatformTransactionManager
のカスタマイズ方法を紹介します。
Spring Boot 1.4までは?
Spring Boot 1.4までは、PlatformTransactionManager
をカスタマイズしたい場合は、以下のいずれかの方法で行う必要がありました。
- Spring Bootの自動定義は使わずに
@Bean
メソッドを用意してカスタマイズする方法(正攻法)
@Bean
PlatformTransactionManager transactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource);
transactionManager.setDefaultTimeout(30);
transactionManager.setRollbackOnCommitFailure(true);
// ...
return transactionManager;
}
-
@Autowired
メソッドを用意してSpring Bootが定義したBeanをカスタマイズする方法
@Autowired
void configureTransactionManager(AbstractPlatformTransactionManager transactionManager) { // Spring Bootが自動設定したBeanがインジェクションしてカスタマイズ
transactionManager.setDefaultTimeout(30);
transactionManager.setRollbackOnCommitFailure(true);
// ...
}
Spring Boot 1.5(1月末リリース予定)からは?
上記方法に加え、Spring Boot 1.5からは、org.springframework.boot.autoconfigure.transaction.PlatformTransactionManagerCustomizer
の実装クラスのBeanをDIコンテナに登録することでカスタマイズすることができるようになります。
public interface PlatformTransactionManagerCustomizer<T extends PlatformTransactionManager> {
void customize(T transactionManager);
}
この仕組みは、複数のアプリケーションでカスタマイズロジックを共有したい場合に役にたつ仕組みだと思います。
PlatformTransactionManagerCustomizerの組み込み実装
実は・・・Spring Bootは、PlatformTransactionManagerCustomizer
インタフェースを実装したクラスを組み込みで提供しています。Spring Bootが提供している組み込み実装を利用すると、AbstractPlatformTransactionManager
に定義されている以下のプロパティの値をカスタマイズすることができます。(gh-7561)
- デフォルトのトランザクションタイムアウト時間(秒)
- コミット時にエラーが発生した際にロールバック処理を行うか否かのフラグ(デフォルト値はfalse=ロールバックメソッドは呼び出さない)
spring.transaction.default-timeout=30
spring.transaction.rollback-on-commit-failure=true
Note:
Springのトランザクションタイムアウト値の扱いについては「MyBatis-Spring 1.3からSpringのトランザクションタイムアウト値が連携される!!(Springのトランザクションタイムアウト値ってどう使われるのか?) 」を、「コミット時にエラーが発生した際にロールバック処理を行うか否かのフラグ」の必要性については「SpringのDataSourceTransactionManagerを使うとエラー時にCommitされる可能性あり!?」をごらんください。
PlatformTransactionManagerCustomizerの実装クラスを作成してカスタマイズする方法
複数のアプリケーションでカスタマイズロジックを共有したい場合は、PlatformTransactionManagerCustomizer
の実装クラスを作成してカスタマイズするのがようでしょう。(共通ライブラリみたいな感じで提供する場合をイメージ)
@Component
public class MyPlatformTransactionManagerCustomizer
implements PlatformTransactionManagerCustomizer<AbstractPlatformTransactionManager> {
@Override
public void customize(AbstractPlatformTransactionManager transactionManager) {
// ... カスタマイズロジックを実装する
}
}
Note:
Spring Bootが生成した
PlatformTransactionManager
がPlatformTransactionManagerCustomizer
のジェネリクスに指定した型に割り当てることができる場合に限り、customize
メソッドが呼び出される仕組みになっています。
Lambda式を使用してカスタマイズする方法 (Java SE 8+)
アプリケーション固有のカスタマイズについては、上記のようなクラスを作らずに、Java SE 8でサポートされたLambda式を使ってPlatformTransactionManagerCustomizer
のcustomize
メソッドをアドホックに実装することもできます。
@Bean
PlatformTransactionManagerCustomizer<AbstractPlatformTransactionManager> transactionManagerCustomizer() {
return transactionManager -> {
// ... カスタマイズロジックを実装する
};
}
Warning:
Lambda式を使うと・・・PlatformTransactionManagerCustomizer
のジェネリクスに指定した型によるcustomize
メソッドの呼び出し制御が効きません(=ジェネリクスにPlatformTransactionManager
を指定しているとみなされてしまう・・・)。
そのため、Spring Bootが生成したPlatformTransactionManager
がジェネリクスに指定した型に割り当てできないと・・・・CalssCastException
が発生するので注意してください!!12/30 15:40 追加
ClassCastException
が発生したら無視するように対応してくれたので、クラスを作成した時と同じ動作になります!!!
PlatformTransactionManagerCustomizerの適用順番
PlatformTransactionManagerCustomizer
は、Spring Bootの組み込み実装(TransactionProperties
)を含め、複数適用することができます。複数のPlatformTransactionManagerCustomizer
をDIコンテナに登録した時の動作は、デフォルトでは不定です。順番を制御したい場合は・・・・
-
@org.springframework.core.annotation.Order
を付与 -
org.springframework.core.Ordered
インタフェースを実装
することで実現することができますが、Spring Bootの組み込み実装(TransactionProperties
)より後にすることはできないみたいです。(少なくても・・・私の環境では組み込み実装より後にすることはできませんでしたが、困ることはない気がしてます)
まとめ
まだリリースされていませんが、Spring Boot 1.5より、PlatformTransactionManager
をカスタマイズをサポートするインタフェース(PlatformTransactionManagerCustomizer
)が追加されたよ〜
ということと・・・
カスタマイズ頻度が多そうな以下のプロパティが、application.properties
(or application.yml
)でカスタマイズ可能になったよ〜
- デフォルトのトランザクションタイムアウト時間(秒)
- コミット時にエラーが発生した際にロールバック処理を行うか否かのフラグ
ということを紹介しました。
Spring Boot 1.5は年明けにRC1、1月末に正式版がリリースされる予定になっています。RC1が出たらSpring Boot 1.4からの変更点を調べようかな〜(と思っています)。
さいごに
たぶんこのエントリーが今年のQiitaの書き納めかな〜と思っています。
来年も気が向くままに投稿しようかな〜と思っているので、すこしでも皆様の役に立てれば幸いです。(へんなところや、もっとこうした方がいいよ〜とかあれば是非コメントください!!)
では、今年も残りあと2日ですが・・・よいお年を〜