Help us understand the problem. What is going on with this article?

Spring Boot 1.5からPlatformTransactionManager用のCustomizerが追加される

More than 3 years have passed since last update.

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コンテナに登録することでカスタマイズすることができるようになります。

PlatformTransactionManagerCustomizerの抜粋
public interface PlatformTransactionManagerCustomizer<T extends PlatformTransactionManager> {
    void customize(T transactionManager);
}

この仕組みは、複数のアプリケーションでカスタマイズロジックを共有したい場合に役にたつ仕組みだと思います。

PlatformTransactionManagerCustomizerの組み込み実装

実は・・・Spring Bootは、PlatformTransactionManagerCustomizerインタフェースを実装したクラスを組み込みで提供しています。Spring Bootが提供している組み込み実装を利用すると、AbstractPlatformTransactionManagerに定義されている以下のプロパティの値をカスタマイズすることができます。(gh-7561)

  • デフォルトのトランザクションタイムアウト時間(秒)
  • コミット時にエラーが発生した際にロールバック処理を行うか否かのフラグ(デフォルト値はfalse=ロールバックメソッドは呼び出さない)
src/main/resources/application.properties
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が生成したPlatformTransactionManagerPlatformTransactionManagerCustomizerのジェネリクスに指定した型に割り当てることができる場合に限り、customizeメソッドが呼び出される仕組みになっています。

Lambda式を使用してカスタマイズする方法 (Java SE 8+)

アプリケーション固有のカスタマイズについては、上記のようなクラスを作らずに、Java SE 8でサポートされたLambda式を使ってPlatformTransactionManagerCustomizercustomizeメソッドをアドホックに実装することもできます。

@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日ですが・・・よいお年を〜 :see_no_evil: :hear_no_evil: :speak_no_evil:

kazuki43zoo
Javaエンジニアで、SpringやMyBatisらへんにそれなりに詳しいです。お仕事のつながりで「Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発」を共著させてもらいました!
https://kazuki43zoo.github.io
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした