SpringMVCでトランザクション管理をおこなう。アノテーションとXMLの設定

SpringFrameWork

SpringMVCでは、アノテーションの設定をおこなうことだけでDBトランザクションの管理をおこなうことができます。


今回は、SpringMVCでトランザクション管理をおこなう方法について説明していきます


SpringMVCでは、トランザクションのスタート位置をアノテーションで指定することにより、トランザクションの開始を定義することができます
トランザクションのスタート位置を定義することにより、どのDB処理を一つのトランザクションとするかをコントロールすることができるということになります。


しかし、こういった制御をおこなうためには、アノテーションの準備とXMLへの設定が必要になります。


トランザクションとは


トランザクションとは何でしょうか?
ここでのトランザクションとは、“データベースのトランザクション”になります。
直訳すると『取引』ですね。


データベース処理では、1回のSQL発行ではデータの整合性が取れない場合が多々あります。
例えば、あるデータをシステムに登録しようとした場合、複数のテーブルにレコードの登録と更新が必要な場合。
テーブルが3つあり、あるデータをシステムに登録しようとした場合、テーブルAにはレコードの登録、テーブルBにはレコードの更新、テーブルCにもレコードの更新が必要だとします。
この場合、テーブルBのレコード更新が失敗したとすると、テーブルAのレコード登録は無かったことにしたいです。
具体的には”コミットしたくない”。


コミットは、全てのDB処理が完了してから(テーブルCへのレコード更新)おこないたいです。


トランザクションの管理

各テーブルへの処理を終わったタイミングでコミットしてしまうと、途中でエラーが発生した場合に、データの整合が取れていない状態でデータができあがってしまいます。
これを避けるために、3つの処理をまとめて考え、3つの処理が全て完了してからコミットします。
途中で、エラー等が発生した場合はロールバックして元に戻します。


この、複数のDB処理を一つにまとめることをトランザクションと呼びます。


どの処理をまとめて一つのトランザクションにするかを考えるのは、安定したシステムを作るのにきちんと考えておきたいポイントです。


common-database-context.xmlの定義


SpringMVCでトランザクション定義をおこなう場合は、「common-database-context.xml」への定義が必要になります。


まずはトランザクション管理するための基本定義です。
トランザクション管理するためのクラス定義と、DBコネクションのデータソース設定です。


「DataSourceTransactionManager」を使用可能な状態にし、「DataSourceTransactionManager」が使用するデータソースを定義します。


<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
    <property name="defaultTimeout" value="10" />
</bean>

プロパティ値として、タイムアウト値も定義します。
10秒です。


通常、SpringMVCで開発したアプリケーションは、Tomcat等のWEBアプリケーション上に配置することになります。
WEBアプリケーションが生成したコネクションプール内のDBコネクションを、SpringMVCが取得してアプリケーションが使用するのが通常になります。


次に、トランザクションを有効にするパッケージの定義とアノテーションの定義。
以下のように定義します。


<aop:config proxy-target-class="false">
    <aop:advisor advice-ref="txAdvice" pointcut="execution(public * jp.co.xxx..*Controller.*(..)) && @annotation(jp.co.xxx.annotation.DbTransaction)" />
</aop:config>

「pointcut」に、トランザクション管理対象のパッケージを定義します。
パッケージを「execution」括ります。


かつ、「@annotation」に、トランザクション開始を意味するアノテーション定義を記載します。
「jp.co.xxx.annotation.DbTransaction」が、アノテーションのJavaクラスになります。


トランザクション管理するアノテーション設定


ここまで準備した「common-database-context.xml」への定義とアノテーション定義で、トランザクション管理をおこなうことが可能になりました。
アノテーションを定義したメソッドがトランザクションの開始位置で、そのメソッドが完了したら自動的にコミットされます。
仮に、メソッドの途中で例外が発生してメソッドが中断された場合はロールバックされます。(コミットされません)
定義としては以下になります。


@DbTransaction
    public void xxx() {

通常は上記でトランザクション管理ができるのですが、個別にトランザクションの開始やコミット・ロールバックをおこないたい場合があります。
独自のトランザクション管理についても可能です。
以下のように、自分でイベントをプログラミングすればよいです。


// トランザクション管理を読み込み
@Autowired(required = false)
private PlatformTransactionManager transactionManager;

public void xxx() {

    // 処理開始
    TransactionStatus status = startTransaction();

        ・
        ・
        ・

    if (isDone) {
        // コミット
        transactionManager.commit(status);
    } else {
        // ロールバック
        transactionManager.rollback(status);
    }
}

まとめ


いかがでしたでしょうか?


SpringMVCでは、アノテーションの準備をするだけでトランザクション管理をおこなうことが可能になります。


システムの方針によるかと思うのですが、トランザクションの単位をどれにするかもいろいろです。
1つのコントローラメソッドについて1トランザクションにするか、サービスのメソッドについて1トランザクションにするか、
といった悩みどころもあります。


システムでルールを統一した上で、SpringMVCで開発を進めていくのがいいかと思います。


それではまた!