S2Tx

トランザクション周りを試してみた。
自分用に結果をメモしておく。

用意するもの

  • HogeDAO (S2DAO用の適当なDAO)
  • HogeDAOClient (HogeDAOをフィールドにDIしてもらいそれを使う)
  • Main (HogeDAOClientをS2Containerから取得して実行する)

(1)トランザクションON、直接コネクション取得禁止
まず、diconファイルに

<component class="test.HogeDAOClient" >
      <aspect>j2ee.requiredTx</aspect>
</component>
<component name="connectionPool" class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl">
	<property name="timeout">600</property>
	<property name="maxPoolSize">10</property>
	<property name="allowLocalTx">false</property>
	<destroyMethod name="close"/>
</component>

と設定する。
HogeDAOClientでは、

	Hoge hoge = new Hoge();
	hoge.setId("変更!"); // --[1]
	hogeDAO.update(hoge);
    
	//throw new RuntimeException(""); // --[2]

のように書いておいてMainから実行する。
結果は正常にコミットされて、DBは正常にUPDATEされる。

と、正常系を確認しておいて、[1]の文字を適当に変えて、[2]のコメントをはずして再実行する。
結果は、RuntimeExceptionのトラップに引っかかり、トランザクションロールバックされて、DBは元のままである。

(2)トランザクションOFF、直接コネクション取得禁止
今度は、diconファイルを

<component class="test.HogeDAOClient" >
	&lt;!--<aspect>j2ee.requiredTx</aspect> ★ここをコメントアウト! -->
</component>
<component name="connectionPool" class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl">
	<property name="timeout">600</property>
	<property name="maxPoolSize">10</property>
	<property name="allowLocalTx">false</property>
	<destroyMethod name="close"/>
</component>

と変更してトランザクションが開始されないようにする。
Mainから実行すると、

org.seasar.framework.exception.SIllegalStateException: [ESSR0311]トランザクションが開始されていません
	org.seasar.extension.dbcp.impl.ConnectionPoolImpl.checkOut(ConnectionPoolImpl.java:98)

となる。
RuntimeExceptionのトラップに引っかかる前に、(トランザクションが開始されていないため)S2DAOで直接JDBCコネクションを取得しようとするが、コネクションプールの設定で許可していないため例外が発生した、ということだ。
これを使うと、トランザクション外のUPDATEが機械的にチェックされるのでバグの発見に役立ちそう。

(3)トランザクションOFF、直接コネクション取得許可
次は、diconファイルを

<component class="test.HogeDAOClient" >
	&lt;!--<aspect>j2ee.requiredTx</aspect> ここをコメントアウトしたまま -->
</component>
<component name="connectionPool" class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl">
	<property name="timeout">600</property>
	<property name="maxPoolSize">10</property>
	<property name="allowLocalTx">true</property> &lt;!-- ★ここをtrueに!--&gt;
	<destroyMethod name="close"/>
</component>

と変更して、トランザクション外のコネクションを取得を許可する。
Mainから実行すると、RuntimeExceptionトラップによって例外が発生する。
が、DBを見てみると変更が反映されてしまっている。
直接JDBCコネクションを取得して使ったため、AutoCommitが効いてしまった、といことだ。

こうして実際に試してみると、ものすごい簡単にトランザクション制御が実現できることをしみじみと実感する。
今までの苦労はいったい…。