// 下階層用テンプレート
#topicpath
----
//ここにコンテンツを記述します。
#contents

**Hibernateとトランザクション管理に関する課題 [#se9f327a]

HibernateベースのDAOを作った場合に、トランザクション処理をどのように記述するかが問題になることがあります。

たとえば下記のような二つのテーブル

#ref(schema.png)


に対してそれぞれMemberDAOとWorkGroupDAOを作ると思います。さらにそのDAOを使用するビジネスメソッド、たとえば

#ref(bl.png)

なんてのが定義されると思います。


このとき、ある処理の場合はメソッド単位でトランザクション管理し、ほかの処理の場合は複数のメソッドにまたがってトランザクション管理したい場合があります。上の例だと、
-addMemberはMemberを登録する
-addGroupはWorkGroupを登録する
-addはMemberをGroupに追加する。引数のメンバーがいなかったらaddMemberでMemberを登録する。引数のグループなかったら、例外をThrowする

とした場合、
-メンバーを登録しようとしてaddMemberを呼び出した場合は、addMember内でトランザクションが開始され、終了すればいい。
-add内でサブルーチン(<-古っ)としてaddMemberが呼ばれる場合は、addでトランザクションが開始され、終了されるのでaddMemberはすでにあるトランザクションに参加すればよい

となります。一つめの例だとaddMember内でトランザクションの開始・終了の処理を書けばよいですが、二つめの例を考えるとaddMember内でトランザクション開始と終了の処理をしちゃうとまずいわけですね。つまりあるメソッドに対してトランザクションのスコープ(境界?)が場面によって異なることがあるのですが、Springではこの辺をトランザクション処理を宣言的に記述することで解決しています。

この辺を考えるために具体例で行きます。今回考えるクラス群の全体像は以下の通りです。

#ref(class.png)

またトランザクション処理を考慮しない状態のSpringの設定は以下の通りになっています。

#ref(bean.png)
#ref(bean2.png)




**Springを使ってトランザクション処理を記述する [#la131913]

さて、SpringではBLのビジネスメソッドに対してトランザクション処理を宣言的に追加することができるといいましたが、以下のようにやります。

まず、BLの名前をuserManagerBLからuserManagerBLTargetに変更し、userManagerBLを新規に作成します。その新たなJavaBeansの型はSpringが提供してくれるProxyで、外部から見たインタフェースは元のuserManagerBLと同じになります。つまり見た目は外部から見たら全く変わっていないことになります。

そのProxyのタグ付けですが、トランザクション設定や、ターゲットになるJavaBeans(元のuserManagerBLのこと)の指定などを記述しておきます。


さて処理の流れですが、実際BLを使うプログラムはuserManagerBLというキーでSpringからJavaBeansを取得するので、処理シーケンスは
 BLを使うプログラム -> userManagerBL
だったのが
 BLを使うプログラム -> userManagerBL -> userManagerBLTarget
となります。

外部から見たら見た目は同じだけど、実際のBLの間に別のクラスが挟まれる用になります。結局、Springのタグ付けは以下のように変更されました。

#ref(after.png)


間に挟まれたPOJOは以下のようにSpringでInjectionされています。
 <bean id="userManagerBL" 
   class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
   <property name="transactionManager">
     <ref local="transactionManager" />
   </property>
   <property name="target"> ↓ターゲットにするPOJOを指定
      <ref bean="userManagerBLTarget" />
   </property>
   <property name="transactionAttributes">
     <props>   ↓POJOのメソッドに対してトランザクションの設定を記述
       <prop key="*">PROPAGATION_REQUIRED</prop>
     </props>
   </property>
 </bean>






----
この記事は
#vote(おもしろかった[2],そうでもない[0])
#vote(おもしろかった[3],そうでもない[0])
-なんか、想定通りにうごかねえなあと思ってたのですが、Linux版のMySQLとWindows版のMySQLのデフォルト値って違うのかな???LinuxのMySQLは、がんばっても勝手にトランザクションが開いちゃうような。。。。Windowsだと、想定通りっぽいんだけだどね -- [[きの]] &new{2006-07-04 00:32:21 (火)};
-MySQLのトランザクションが開かれたとき、 org.hibernate.transaction.JDBCTransaction - begin がログにでた。 -- [[きの]] &new{2006-07-05 00:25:08 (水)};
-まとめると、こんな感じ。基本的にMySQLはトランザクションを開かないとInsertとかは反映されない。ただし、Linux版は明示的にトランを開かないとき、誰かが勝手にトランザクションを開始して、勝手にコミットする。Windows版は自分で開く・閉じるをしないと、DBに反映されない。トランザクションが開かれたとき、上のログが出力される。 -- [[きの]] &new{2006-07-05 00:26:44 (水)};
-書き途中で、じかんがないっ -- [[きの]] &new{2006-07-20 22:28:05 (木)};

#comment
#topicpath


SIZE(10){現在のアクセス:&counter;}

トップ   編集 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS