[spring]10.4 Synchronizing resources with transactions

JDBCHibernate,JDOなどといった永続化のAPIを、直接/間接的に扱うアプリケーションにおいて、トランザクション管理下にあるリソースを取得する方法を説明する。またあわせて、PlatformTransactionManagerを通してトランザクションとの同期が行なわれる方法についても説明する。

10.4.1 High-level synchronization approach

理想的なアプローチは、

  1. Springが提供する、テンプレートベースの永続化層APIを用いる
  2. ORMのAPIを、Transaction-Awareな(トランザクションを認識してる)FactoryBeanから取得する*1
  3. ネィティブなResourceFactoryを管理するプロキシを取得する(??)

のどれかである(最後のは訳違うかも…)。上記の方法では、取得したリソースは内部的に勝手にライフサイクル管理をしてくれる。アプリケーションコードにはこれらの処理が入らないので、ビジネスロジックに集中できる。NativeなORMのAPIを使うか、もしくはJDBCTemplateを使ったアプローチが一般的。これらのやり方については、あとで説明する。

10.4.2 Low-level synchronization approach

DataSourceUtils (JDBCの場合), EntityManagerFactoryUtils (JPAの場合), SessionFactoryUtils (Hibernateの場合), PersistenceManagerFactoryUtils (JDOの場合)などを呼び出してリソースを取得する方法。*2もしアプリケーションで直接リソースやNativeな永続化APIを扱いたい場合は、これらのユーティリティを使ってSpringが管理するインスタンスを取得する。

例えばJDBCの場合はDataSoruce#getConnectionの代わりに,DataSourceUtils#getConnectionを呼び出す。


Connection conn = DataSourceUtils.getConnection(dataSource);

もしすでにトランザクションに関連付けられたコネクションが存在したら、そのコネクションが返される。そうでなければこの時点でコネクションが生成され、トランザクションに紐づけられた状態で返却される。なお以前に述べたようにすべてのSQLExceptionはCannotGetJdbcConnectionExceptionにラップされるので例外ハンドリングは楽です。

なおこのやり方での取得はSpringのトランザクション管理がなくても可能。ただJDBCSupport/JPASupport/HiberateSupportが使える場合は、こんなやり方はしない方が全体的にすっきるするのでやらないほうが良い。

10.4.3 TransactionAwareDataSourceProxy

最下位のAPIとしてTransactionAwareDataSourceProxyが存在する。これはDataSourceのProxyで、Springのトランザクション機構とひもづける機能を提供する。この点ではJavaEEサーバーが提供するJNDIDataSourceに似ている。このクラスは、引数として標準のJDBCDataSourceを受け取る既存のクラスをSpringのトランザクションにひもづけるようなケース以外では使うべきではない。

*1:http://static.springsource.org/spring/docs/1.2.9/api/org/springframework/orm/toplink/AbstractSessionFactory.html

*2:「Transaction-Awareな(トランザクションを認識してる)FactoryBeanから取得する」とどう違うのか?ORMAPIと永続化APIを分けてる?