Red Hat Training

A Red Hat training course is available for Red Hat JBoss Web Server

12.2.2. JTA を使用する

永続化層をアプリケーションサーバー (例えば、 EJB セッション Bean の背後) で実行する場合、 Hibernate から取得するすべてのデータソースコネクションは、自動的にグローバル JTA トランザクションの一部になります。EJB を使わずに、スタンドアロンの JTA 実装を導入することもできます。JTA 統合のために、Hibernate は2つの戦略を提供します。
Bean 管理トランザクション(BMT)を使い、Transaction API を使う場合、 Hibernate はアプリケーションサーバーに BMT トランザクションの開始と終わりを告げます。すなわち、トランザクション管理のコードは、管理のない環境と同じになります。
// BMT idiom
Session sess = factory.openSession();
Transaction tx = null;
try {
    tx = sess.beginTransaction();

    // do some work
    ...

    tx.commit();
}
catch (RuntimeException e) {
    if (tx != null) tx.rollback();
    throw e; // or display error message
}
finally {
    sess.close();
}
トランザクション境界として Session を使いたい場合、簡単にコンテキストを伝播する getCurrentSession() 機能があるので、 JTAの UserTransaction API を直接使用すべきでしょう。
// BMT idiom with getCurrentSession()
try {
    UserTransaction tx = (UserTransaction)new InitialContext()
                            .lookup("java:comp/UserTransaction");

    tx.begin();

    // Do some work on Session bound to transaction
    factory.getCurrentSession().load(...);
    factory.getCurrentSession().persist(...);

    tx.commit();
}
catch (RuntimeException e) {
    tx.rollback();
    throw e; // or display error message
}
CMT では、トランザクション境界をセッション Bean のデプロイメントディスクリプタで定義し、プログラムでは行いません。コードは次のように少なくなります:
// CMT idiom
 Session sess = factory.getCurrentSession();

 // do some work
 ...
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() の使用を簡単に避けることができます。