Spring Boot DB連携

1つのトランザクションで複数のDBを更新するアプリケーションでChainedTransactionManagerを利用してみた

Spring Bootを利用したアプリケーションでDB接続を利用する際、@Transactionalアノテーションをつけたメソッド内でDB更新処理を実装するようにすると、そのメソッド単位で、DB更新処理が成功した場合にコミットし、失敗した場合にロールバックをすることができるが、同一トランザクション内で複数DBに接続するアプリケーションの場合は、複数DBのトランザクション管理を行うための仕組みが別途必要になる。

その対応案の1つとして、ChainedTransactionManagerを利用し、接続先DBをまとめて管理したChainedTransactionManagerクラスのインスタンスをあらかじめ定義しておき、@Transactionalアノテーション内で指定するtransactionManager属性にChainedTransactionManagerを指定するという方法がある。

今回は、Spring Bootアプリケーション内でMyBatisフレームワークを利用する状態で、1つのトランザクションで複数のDBを更新する処理を記載し、ChainedTransactionManagerを利用した@Transactionalアノテーションの挙動を調べてみたので、共有する。

前提条件

下記記事の実装が完了していること。

複数DBに接続するアプリケーションでSpring Bootの@Transactionalアノテーションの挙動を調べてみたSpring Bootを利用したアプリケーションでDB接続を利用する際、@Transactionalアノテーションをつけたメソッド内でD...

サンプルプログラムの作成

作成したサンプルプログラムの構成は以下の通り。
サンプルプログラムの構成
なお、上記の赤枠は、前提条件のプログラムから追加/変更したプログラムである。

build.gradleの内容は以下の通りで、ChainedTransactionManagerを利用するために、Spring Data Commonsのライブラリを追加している。

また、ChainedTransactionalアノテーションを定義しているクラスは以下の通りで、OracleとSQL Serverのトランザクションマネージャを1つにまとめて定義している。

なお、OracleのトランザクションマネージャはDemoOraDataSourceConfigクラスで、SQL ServerのトランザクションマネージャはDemoSsDataSourceConfigクラスで定義している。

さらに、サービスクラスの内容は以下の通りで、OracleとSQL Serverのユーザーデータテーブル(user_data)を1つのトランザクションで更新する処理を定義している。

また、Spring Bootのメインクラスの内容は以下の通りで、サービスクラスのtransUserDataメソッドを呼び出している。

その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/java/tree/master/spring-boot-chained-transaction-manager/demo



「AOMEI Backupper」は様々な形でバックアップ取得や同期処理が行える便利ツールだったパソコン内のデータを、ファイル/パーティション/ディスク等の様々な単位でバックアップしたり、バックアップ時のスケジュール設定やリアルタイ...

サンプルプログラムの実行結果

サンプルプログラムの実行結果は以下の通りで、同一トランザクション内でOracleとSQL Serverの両方のDB更新が成功するとコミット、どちらか1つでも失敗するとロールバックされることが確認できる。

1) 以下のように、DemoServiceクラスの2回目の氏名更新時の設定値を、OracleもSQL Serverも更新成功する値に設定する。
サンプルプログラムの実行結果_1

2) 1)の状態でSpring Bootのメインクラス(DemoApplication.java)を実行した結果、コンソールログに出力される内容は以下の通り。
サンプルプログラムの実行結果_2

3) 1)の状態で、実行前後でOracleとSQL ServerのUSER_DATAテーブルの値を確認した結果は以下の通りで、コミットされ氏名が更新されることが確認できる。

<実行前(Oracle)>

サンプルプログラムの実行結果_3_1

<実行前(SQL Server)>

サンプルプログラムの実行結果_3_2

<実行後(Oracle)>

サンプルプログラムの実行結果_3_3

<実行後(SQL Server)>

サンプルプログラムの実行結果_3_4



ウズウズカレッジJavaコースはわかりやすい動画教材と充実した就業サポートで優良企業を目指せるプログラミングスクールだったJavaは、世界中で広く使われていて、現在の需要が高く将来性もある開発言語になります。 https://www.acrovision....

4) 以下のように、DemoServiceクラスの2回目の氏名更新時の設定値を、Oracleは更新失敗し、SQL Serverは更新成功する値に設定する。
サンプルプログラムの実行結果_4

5) 4)の状態でSpring Bootのメインクラス(DemoApplication.java)を実行した結果、コンソールログに出力される内容は以下の通り。
サンプルプログラムの実行結果_5

6) 4)の状態で、実行前後でOracleとSQL ServerのUSER_DATAテーブルの値を確認した結果は以下の通りで、OracleもSQL Serverもロールバックされ氏名が更新されないことが確認できる。

<実行前(Oracle)>

サンプルプログラムの実行結果_6_1

<実行前(SQL Server)>

サンプルプログラムの実行結果_6_2

<実行後(Oracle)>

サンプルプログラムの実行結果_6_3

<実行後(SQL Server)>

サンプルプログラムの実行結果_6_4



「DesignEvo」は多くのテンプレートからロゴを簡単に作成できるツールだった多くのテンプレートが用意されていてロゴを簡単に作成できるツールの一つに、「DesignEvo」があります。今回は、「DesignEvo」...

7) 以下のように、DemoServiceクラスの2回目の氏名更新時の設定値を、SQL Serverは更新失敗し、Oracleは更新成功する値に設定する。
サンプルプログラムの実行結果_7

8) 7)の状態でSpring Bootのメインクラス(DemoApplication.java)を実行した結果、コンソールログに出力される内容は以下の通り。
サンプルプログラムの実行結果_8

9) 7)の状態で、実行前後でOracleとSQL ServerのUSER_DATAテーブルの値を確認した結果は以下の通りで、OracleもSQL Serverもロールバックされ氏名が更新されないことが確認できる。

<実行前(Oracle)>

サンプルプログラムの実行結果_9_1

<実行前(SQL Server)>

サンプルプログラムの実行結果_9_2

<実行後(Oracle)>

サンプルプログラムの実行結果_9_3

<実行後(SQL Server)>

サンプルプログラムの実行結果_9_4

要点まとめ

  • 同一トランザクション内で複数DBに接続するアプリケーションの場合は、接続先DBをまとめて管理したChainedTransactionManagerクラスのインスタンスをあらかじめ定義しておき、@Transactionalアノテーション内で指定するtransactionManager属性にChainedTransactionManagerを指定することで、そのメソッド単位で、DB更新処理が成功した場合にコミットし、失敗した場合にロールバックをすることができる。