システム部の福原と申します。
前回に引き続き、あーだこーだしている日常を並べていきます。
ご笑覧あれー。
前回のあらすじ
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 TransactionException
void commit(TransactionStatus status) throws TransactionException
void 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
を操作するプログラムを書いてトランザクション管理するときはこういうコードになるらしい。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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アーティファクトにするとしようか。
(まだ続く!)