*

Spring5入門[AbstractRoutingDataSourceで複数DBへの接続とトランザクション制御]


スポンサードリンク



今回はSpring MVCから複数データベースに接続とトランザクション制御の内容を記載させていただきます。

対象アプリはといってもgetの1メソッドだけなのですが・・・

http://localhost:8080/abstractRoutingDataSourceSample/login?userId=region1User&password=region1UserPass&regionId=rejion1

にアクセスすると、引数で指定したregionIdのデータベースに接続し、
usersテーブルを検索して、ユーザに認証を行い。
成功の場合は成功ページ、失敗の場合は失敗のページに遷移する。
ただそれだけの中身となります。

gradleでxml設定ファイルベースの内容となります。
データベースのアクセスはspring-jdbcを利用した例となります。

全ソースは
AbstractRoutingDataSourceSample.zip
からダウンロード可能です。

普段はdoma2を利用しておりますので、次回エントリーで
データベースのアクセス部分をdoma2にしたものを記載させていただく予定です。

概要

HTTPのリクエストのregionIdパラメタを参照して、AOPのポイントカットで呼び出されるメソッドで
接続先のデータソースを識別するオブジェクトをスレッドローカルに格納し、
org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource
を継承したクラスが格納されたオブジェクトを返却する。
これによって動的なデータソースの切り替えを可能にする。
との例となります。

AOPのポイントカットを一段設けることで、HTTPの1リクエスト内での複数データソース切り替え
も実現できます。

HTTPの1リクエスト内での接続先DBが単一である場合は、AOPのポイントカット部分は必要ありませんので、
実際の利用要件でこの部分の必要可否は判断いただければと思います。

build.gradle

build.gradleは以下の通りです。

springframeworkのコア的な物とwebmvc, jdbcを利用します。
DBはheをインメモリで利用します。
ユニットテストはJUnit5となります。

モックフレームワークは今回は利用しておりません。
トランザクション制御ですので、モックは利用せずにテストを実装します。

AOPのポイントカットで接続先のデータベースを切り替えるますので、aspectjを利用します。

springのben定義ファイル

src/main/resources/META-INF/spring/contextConfig.xml
として定義するben定義ファイルは以下の通りです。

データソース定義

今回は例ではdataSourceRejion1とdataSourceRejion2を動的に切り替えます。

この動的な切り替え部分が40-48行目となります。

beanとして定義しているjp.helpfulness.javaworld.sample.common.RoutingDataSourceは
org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource
を継承したクラスです。

key-typeで指定しているjp.helpfulness.javaworld.sample.common.DataSourceTypeはenumで
entry keyのキーがenumの対応する定義であり、value-refが対応するデータソースのbeanIdとなります。
entry key=”REGION_1″ value-ref=”dataSourceRejion1″は定義ファイルの48-53行目のdataSourceRejion1の定義に紐づけられます。

同様に、entry key=”REGION_2″は56-61行目のdataSourceRejion2の定義に紐づけられます。

DataSourceTypeは以下の通りです。

RoutingDataSourceは以下の通りです。

DbContextHolder(後述)で保持されているスレッドローカルな値のDataSourceTypeを返却するだけです。
これによってDBへのコネクションの要求時に動的に接続先が変更できるようになります。

データソースの切り替え

77-88行目で定義しております。

SwitchingDataSourceAspectのswitchDataSourceメソッドで
引数のregionIdに対応するデータソース(DataSourceType)をDbContextHolderクラスが保持するThreadLocalな変数に保存します。

AOPのポイントカットはjp.helpfulness.javaworld.sample.service配下のクラスのメソッド
を対象としています。

SwitchingDataSourceAspectは以下の通りです。

DbContextHolderは以下の通りです。

switchDataSource(ProceedingJoinPoint joinPoint)
の中身が少しイマイチですね・・・
引数もrejionIdの参照インデックスが固定なため、汎用性にかけると言えます。

まあ、あくまでもサンプルなのでしょうがないのですが・・・
まあ、まあ、実際のプロダクトコード実装時には

・複数のログイン画面を用意して、ログイン画面毎にDB接続先を切り替える。
・ログイン後にDB接続先を判定し、セッションに接続先を保持し、DB接続先として利用する。

などの内容になると思います。

確認用の処理

確認用の処理クラスはLoginController、LoginService、UserDao
となります。

http://localhost:8080/abstractRoutingDataSourceSample/login?userId=region1User&password=region1UserPass&regionId=rejion1
が物語っているように
getのリクエストを受け付けるLoginControllerのloginメソッド
LoginServiceのlogin(String regionId, String userId, String password)
さらにUserDao.selectById(String uesrId)
とのコールスタックとなります。

トランザクション制御を行うために
LoginService.loginに@Transactionalを付与しております。
(本来はトランザクションが必要な処理でなないのですが・・・)

今回のサンプルはブラウザからの動作確認も可能なのですが、
やはりユニットテストも必要だと思いますので、LoginControllerTestも実装しております。
といってもDB接続の切り替えを行うので純粋なユニットテストとは言えないのですが・・・

LoginController

LoginControllerは以下の通りです。

DbContextHolder.clearの呼び出し忘れてますね・・・
スレッドリークが発生しますので、実際のプロダクトコードでは呼び出す処理を実装する必要があります。

LoginService

LoginServiceは以下の通りです。

UserDao

UserDaoは以下の通りです。

LoginControllerTest

LoginControllerTestは以下の通りです。

testLogin_successの引数が
“region1User”, “region1UserPass”,”rejion2″
の実行時のログの抜粋は以下のようになります。

2-5行目
SwitchingDataSourceAspect.switchDataSourceでrejion2に対応するデータソースの
DataSourceTypeをDbContextHolderにセット
6行目 Creating new transaction
7行目 RoutingDataSource.determineCurrentLookupKeyでREGION_2が返却される。
8-10行目 REGION_2へのコネクションの生成
10行目 LoginService.loginの開始
17行目 Committing JDBC transaction on Connection

となっており、期待すべき動作が実現できていることが確認できます。


スポンサードリンク



関連記事

Eclipse(4.3,4.4)のJava言語のリファクタリング機能の使い方[リファクタリングの説明と「名前変更」と「移動」]

本エントリーでは、Eclipse(4.3,4.4)の「リファクタリング」機能の使い方を説明させていた

記事を読む

Spring5入門[簡単なWebアプリのユニットテストをJUnit5とJMockitで作成]

Spring5入門ではJUnit4とmockitを利用したSpringのController、Ser

記事を読む

Java超入門 with Eclipse[4:クラスに関する基礎知識(修飾子とクラスとインスタンスと変数)]

前回は、Javaの基本であるクラスの基本的な知識をざっくりと説明させていただいたあと、 packa

記事を読む

java8(JDK8)の新機能のラムダ式の利用方法をEclipseとJUnitで説明[その2:関数型インターフェースを例としたラムダ式]

「JDK8(Java 8)の新機能のラムダ式の利用方法」では、 指定できる場所の概説と関数型インタ

記事を読む

Eclipse(4.3,4.4)の使い方[各画面エリアの名称とパースペクティブのビューのカスタマイズ]

本エントリーでは、Eclipse(Eclipse4.3,4.4)の各画面エリアの名称の説明と、ビュー

記事を読む

JUnit入門その1[Eclipse4.4のJUnitプラグインの基本的な使い方]

利用する環境の作成につきましては、「Eclipseの使い方(Windows環境のEclipse4.3

記事を読む

JUnit入門その9[@RunWithアノテーションを利用したテストの作成]

今回は@RunWithアノテーションを利用したテストの作成方法を説明させていただきます。 JU

記事を読む

Eclipse(4.3,4.4)の使い方[パースペクティブのツールバーのカスタマイズ(「コマンド・グループ可用性」と「ショートカット」タブ)]

「パースペクティブのカスタマイズ」画面には、以下の4つのタブが存在しております。 ツール・バ

記事を読む

java8(JDK8)の新機能をEclipseとJUnitで[インターフェースのデフォルト実装の使い方]

本エントリーでは、まずSAM Typeの説明をさせていただきます。 その流れの中で「java8の新

記事を読む

JDK8(java 8)の新機能のラムダ式の利用方法[その3:java8が用意している関数型インターフェース]

[その2:関数型インターフェースを例としたラムダ式] と説明させていただいておりますが、

記事を読む

Message

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Spring5入門[AbstractRoutingDataSourceで複数DBへの接続とトランザクション制御]

今回はSpring MVCから複数データベースに接続とトランザクション

Eclipse Oxygen Update 1 (4.7.1)を利用してJUnit5の公式ガイドの内容を実践してみる。

いよいよJUnit5が本格的に利用できる環境が整ってきました。

Spring5入門[簡単なWebアプリのユニットテストをJUnit5とJMockitで作成]

Spring5入門ではJUnit4とmockitを利用したSpring

Spring5入門[STS(Spring Tool Suite)で簡単なWebアプリの典型的なユニットテストの実現方法]

前回は「Spring入門」で、Spring MVCを利用した簡単なWe

Spring5入門[STS(Spring Tool Suite)の環境作成と簡単なWebアプリの作成]

Struts1ももう過去の遺物になり、SAStrutsもEOLとなりも

→もっと見る

Optimization WordPress Plugins & Solutions by W3 EDGE
PAGE TOP ↑