システム部の福原と申します。
前回に引き続き、あーだこーだしている日常を並べていきます。
ご笑覧あれー。
前回のあらすじ
Spring 2.5 から ChainedTransactionManager が非推奨になりました。
そこで、このクラスを勝手Mavenアーティファクトにして弊社内Mavenリポジトリで管理することになりました。
詳細はこちら:
ソースコードの概要
一応ソースコード丸コピとはいえ、自前アーティファクトとして管理することになる。ソースの内容を把握しておこう。
ソースはここにある。読むぞー。
<<ドタドタ・バタリ>>
ChainedTransactionManager と、関連するクラスは、org.springframework.data.transaction パッケージに閉じている。ソースは4本ある。
- ChainedTransactionManager.java
- MultiTransactionStatus.java
- SpringTransactionSynchronizationManager.java
- SynchronizationManager.java
import文を見る限り、これらのクラスの依存先はspringが外部に公開しているクラスだけのようだ。
spring内部向けのクラスに依存していないから、今後springがバージョンアップしても影響は少ないと思われる。
公開パッケージの変更は非互換が発生することだしそう滅多に起きないだろう。
各クラスの役割
とりあえず、クラス図書いてみようか。

うむ。ChainedTransactionManager を中心に機能をクラスに分けている感じかな。
それぞれのクラスの役割はというと、、、
ChainedTransactionManager クラス
ChainedTransactionManager は、PlatformTransactionManager の実装クラスで、以下3本のメソッドの実装を持つ。
TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionExceptionvoid commit(TransactionStatus status) throws TransactionExceptionvoid rollback(TransactionStatus status) throws TransactionException
トランザクションの開始と終了とロールバックをするときに、それぞれの処理をする。 Spring的には自前のトランザクションマネージャを作るときは、PlatformTransactionManagerの実装クラスを作れってことなのだな。
MultiTransactionStatus クラス
MultiTransactionStatus は TransactionStatus の実装クラスで、複数ある PlatformTransactionManager と TransactionStatus をまとめて保持するクラスだ。つまり1つであって、かつ複数である TransactionStatus なんだ。 ChainedTransactionManager が操作をされたときにそれぞれの PlatformTransactionManager に対して操作を行う仕組みだ。
あと内部クラスとして SavePoints クラスがある。
セーブポイントのサポートもしているようだ。(けれど、弊社要件的にはいらないかもな。。。)
SpringTransactionSynchronizationManager 列挙
SpringTransactionSynchronizationManager は、TransactionSynchronizationManager が使われたときの対応の処理をしている。
まず、Springの機能としてTransactionSynchronizationManager を使うと、トランザクションのコミット前や後のタイミングで実行したい処理を登録できる。
で、 ChainedTransactionManagerでは、現在のスレッドで初めてTransactionSynchronizationManagerが使われた時だけTransactionSynchronizationManagerの初期化と終了の処理を行っている。
終了の処理ってのはトランザクション終了時に TransactionSynchronizationManager に登録された処理を消し込むことだ。
そうでないとき、、つまり既に使用中の時はなにもしない。
これの目的はなんだろう?自分で使い始めたときは登録された処理をあとに残さないようにしているってことか。
既に使われているときは、(最初に使ったどこかの処理で管理されるだろうから)何もしないと。
実装としては、ChainedTransactionManagerから呼ばれている処理を全部TransactionSynchronizationManager に移譲している。
やっていることはそれだけ。
状況判断はChainedTransactionManagerがやっている。
SynchronizationManager インターフェース
SynchronizationManager インターフェースは、SpringTransactionSynchronizationManager の実装対象のインターフェースだ。
ChainedTransactionManagerは、SynchronizationManager型のフィールドを経由してSpringTransactionSynchronizationManagerを使っている。
この構造の意図はなんだろう?将来のなにかのために多態ができるようにしたかったのかな?
現在の挙動だと ChainedTransactionManager から直接 TransactionSynchronizationManager を呼んでいる。
だから今の所インターフェースを使うほどの用途はなさそうに見えるな。
処理の流れ
処理の流れはどうなるだろうか。
本家のドキュメントによるとPlatformTransactionManager を操作するプログラムを書いてトランザクション管理するときはこういうコードになるらしい。
val def = DefaultTransactionDefinition()
// explicitly setting the transaction name is something that can be done only programmatically
def.setName("SomeTxName")
def.propagationBehavior = TransactionDefinition.PROPAGATION_REQUIRED
val status = txManager.getTransaction(def)
try {
// put your business logic here
} catch (ex: MyException) {
txManager.rollback(status)
throw ex
}
txManager.commit(status)
この流れを元に、txManager が、ChainedTransactionManagerだったときの処理の流れを図にするとこんな感じかな。
実際にはトランザクション管理の処理がSpringによってDIよろしく差し込まれて動作するから本当の流れではない。
でもクラスの使われ方や役割はわかる。(それにしてもでかい図になってしまった!)

うむやはり、開始とコミットとロールバックをするときに、それぞれのトランザクションマネージャーのそれぞれのメソッドを呼び出す形だな。
ちなみに例外発生時は常にrollbackを呼ぶ流れになるようだ。
例えば一番最後のデータベースへのcommitで例外が発生したら、そのDBのrollbackが呼ばれる。
最初のDBへは何もしない。(既にcommitされている。)
これは不整合を起こすかもだが、弊社要件的には他のやり方で対応するから問題ない。
まとめ
よし大体わかった!気がする!
ある程度わかっておけば、今後なにかspringに変化があってもついていけるだろう。(Spring Boot 3系どうなるだろうか。どきどき。ていうかあとになってDeprecatedやめますとか言われないといいなー。)
ではこれらのソースでMavenアーティファクトにするとしようか。
(まだ続く!)
