12.2.2. JTA を使用する
永続化層をアプリケーションサーバー (例えば、 EJB セッション Bean の背後) で実行する場合、 Hibernate から取得するすべてのデータソースコネクションは、自動的にグローバル JTA トランザクションの一部になります。EJB を使わずに、スタンドアロンの JTA 実装を導入することもできます。JTA 統合のために、Hibernate は2つの戦略を提供します。
Bean 管理トランザクション(BMT)を使い、
Transaction API を使う場合、 Hibernate はアプリケーションサーバーに BMT トランザクションの開始と終わりを告げます。すなわち、トランザクション管理のコードは、管理のない環境と同じになります。
トランザクション境界として
Session を使いたい場合、簡単にコンテキストを伝播する getCurrentSession() 機能があるので、 JTAの UserTransaction API を直接使用すべきでしょう。
CMT では、トランザクション境界をセッション Bean のデプロイメントディスクリプタで定義し、プログラムでは行いません。コードは次のように少なくなります:
CMT/EJB の中では、ロールバックが自動的に実施されます。セッション Bean のメソッドにより投げられた処理されていない
RuntimeException は、グローバルトランザクションをロールバックするようコンテナに伝えるためです。これは、BMT もしくは CMT と一緒に Hibernate Transaction API を使う必要はまったくなくトランザクションにバインドする「現在の」セッションを自動伝搬できます。
Hibernate のトランザクションファクトリを設定する際に、JTA を直接使う (BMTの) 場合は
org.hibernate.transaction.JTATransactionFactory を、 CMT セッション Bean の中では org.hibernate.transaction.CMTTransactionFactory を選択してください。hibernate.transaction.manager_lookup_class をセットすることも忘れないでください。なお、hibernate.current_session_context_class は、セットしないか(後方互換)、"jta" をセットしてください。
getCurrentSession() オペレーションは、JTA 環境で欠点が1つあります。デフォルトで使われる after_statement コネクションリリースモードを使用する上で、警告が1つあります。JTA 仕様の制約のために、scroll() または iterate() が返した、閉じられていない ScrollableResults または Iterator インスタンスを Hibernate が自動的にクリーンアップすることはできません。finally ブロックの中で、 ScrollableResults.close() または Hibernate.close(Iterator) を明示的に呼び出して、基盤のデータベースカーソルを解放 しなければなりません。多くのアプリケーションでは、 JTA か CMT コードから、scroll() や iterate() の使用を簡単に避けることができます。