「ぼっち SpringSource Advent Calendar 2012」開催中ですが、
こちらはそのあとで見つけて、勢いで参加したw Spring Advent Calendar 2012 3日目の記事になります。
2日目は@mike_neckさんの
mike、mikeなるままに…: 今更Spring Rooを紹介しる
http://mikeneck.blogspot.jp/2012/12/spring-roo.html
でした。おー、Rooですね!CUIのみでプログラミングレスなところがレトロで新しいよねv ってことで、3日目、行きましょう。
Springでデータベース接続と処理を行う時、LocalSessionFactoryBeanという接着剤の役割クラスを使うことで簡単便利になりました。今回は、そこから呼ばれるDataSourceクラスをちょっと変わった基底DataSouceクラスに変更して、動的に接続先を切り替える実装について書いてみようと思います。
主人公となるクラスはAbstractRoutingDataSourceです。
AbstractRoutingDataSource(JavaDoc)
使い方の簡単なイメージはこんな感じ。
- AbstractRoutingDataSourceを継承した新しいクラスAを作成する
- AのプロパティTargetDataSourcesを切替える対象となるDatasouceのリストで初期化する
- AをSessionFactoryに組み込む
これだけ?はい、追加で必要な事はこれだけですw。
実際に、すでに稼働している月次データベースアプリケーションに対して、1月~12月の月ごとにあるデータベース(テーブルは既存と全て同じものをもつ12個の新規データベース)に自動で接続先を切り替えてアクセスするように変更する、という要件をサンプルケースとしてみます。
作成するポイントは次のとおり。
- 月ごとに接続する先を自動で振り分ける処理を作る。
- 作成したクラスと接続先の設定をアプリケーションコンテキストに記述する。
まずはAbstractRoutingDataSourceを継承したMyRoutingDataSourceクラスを作成。
1: import java.util.Calendar;
2: import sun.util.calendar.LocalGregorianCalendar.Date;
3:
4: public class MyRoutingDataSource extends AbstractRoutingDataSource {
5:
6: @Override
7: protected Object determineCurrentLookupKey() {
8: Calendar nowDate = Calendar.getInstance();
9: return String.format("db_%03d", nowDate.get(Calendar.MINUTE));
10: }
11:
12: }
determineCurrentLookupKeyメソッドでSessionFactoryに接続先を決定させるKeyをreturnする処理を実装します。SessionFactoryはそのKeyを基にTargetDataSourcesのリストからDataSourceを取得します。
次に、作成したクラスを既存のコンテキストに組み込み、接続先データソースのリストをTargetDataSourcesに設定します。(注:サンプルでは細かな設定部分を省略しています。)
1: <!-- db_001からdb_012までのDatasourceを作成。細かな設定は省略 -->
2: <bean id="db_001" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
3: <property name="url" value="jdbc:hsqldb:hsql://192.168.30.5:9001/jan"/>
4: </bean>
5:
6: <bean id="db_002" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
7: <property name="url" value="jdbc:postgresql://192.168.30.78:5432/feb"/>
8: </bean>
9: <!-- 同じように003~012まで作成 -->
10:
11: <!-- 同じようにデータベース名をキーとしたマップで初期化する -->
12: <bean id="dataSource" class="katagiri.sample.advent2012.MyRoutingDataSource">
13: <property name="targetDataSources">
14: <map key-type="blog.datasource.CustomerType">
15: <entry key="db_001" value-ref="db_001"/>
16: <entry key="db_002" value-ref="db_002"/>
17: <entry key="db_003" value-ref="db_003"/>
18: <!-- 同じように003~012まで作成 -->
19: </map>
20: </property>
21: <property name="defaultTargetDataSource" ref="db_001"/>
22: </bean>
23:
24: <!-- SessionFactoryは既存のものをそのままなので詳細は省略 -->
25: <!-- DAOは既存のものをそのままなので省略 -->
これで実装作業が終わりました。
本来なら大量コーディングが予想されただろう実装が、「こんなこともあろうかと」基底クラスがあってそれを継承するだけ、コンテキストに設定を加えていくだけ、と、とても少ない作業で出来てしまいました。
まさにSpringFramework有難う!
次はJSUGでご活躍されている@tikeda123さんの記事になります。こちらも要ちぇきら♪