第8回 J2EEのトランザクション処理


 トランザクション属性

 ここからは、トランザクションとEJBについて解説しましょう。

 

 トランザクション属性の設定

 トランザクション属性は、deployment descriptorに記録されます。ですから、いろいろなところでこの属性を動かすことは可能なのですが、基本的にはEJBの開発者がこの属性をキチンと設定しておくことが必要です。

 トランザクション属性の指定は、ビーン全体に対しても、個々のメソッドごとにも可能です。ビーン全体にはある属性を指定したのに、そのビーンの内部のメソッドに、それとは異なる属性を指定した場合には、メソッドへの指定が優先されます。

 トランザクション属性の指定は、セッション・ビーンに対しても、エンティティ・ビーンに対しても可能なのですが、少し違いも存在します。セッション・ビーンでは、この属性の指定が可能なのは、リモート・インターフェイスで定義されたビジネス・メソッドだけで、ホーム・インターフェイスのcreateメソッドには許されないのですが、エンティティ・ビーンの場合には、ビジネス・メソッドだけでなく、create、remove、ファインダ・メソッドにもこの属性設定が可能です。

 

 Container-Managed Transactionsのロールバック

 Container-Managed Transactionsがロールバックするのは2つの場合があります。1つは、システム例外が投げられた場合です。このとき、コンテナは、自動的に、トランザクションをロールバックします。もう1つの場合は、EJBContextインターフェイスのsetRollbackOnlyメソッドが呼び出された場合です。このメソッドは、コンテナに、トランザクションのロールバックを命じます。

 ですから、システム例外ではなくアプリケーション・レベルの例外でトランザクションのロールバックを起こそうとするなら、例外処理のコードの中で、まず、setRollbackOnlyメソッドを呼び出すことです。次の例は、BankEJBビーンで、残高がマイナスにならないようなチェックを行っているところです。InsufficientBalanceExceptionは、アプリケーション・レベルの例外ですから、まずsetRollbackOnlyメソッドが呼ばれています。一方、EJBExceptionはシステム例外ですので、この場合にもロールバックは実行されることになります。

public void transferToSaving(double amount) throws
  InsufficientBalanceException {

  checkingBalance -= amount;
  savingBalance += amount;

  try {
    updateChecking(checkingBalance);
    if (checkingBalance < 0.00) {
      context.setRollbackOnly();
      throw new InsufficientBalanceException();
    }
    updateSaving(savingBalance);
  } catch (SQLException ex) {
    throw new EJBException
      ("Transaction failed due to SQLException: "
      + ex.getMessage());
  }
}


 

 Bean-Managed Transactionsの場合

 Container-Managed Transactionsは、コードを大幅に少なくすることができるメリットがある半面、次のような細かなトランザクションの制御は難しくなります。

トランザクションA開始
....
テーブルA更新
....
 もし、条件Xが満たされていれば
   トランザクションA成功
 あるいは、条件Yが満たされていれば
   テーブルB更新
   トランザクションA成功
 そのいずれでもなければ、
   トランザクションA失敗
   トランザクションB開始
   テーブルC更新
   トランザクションB成功

 こうしたときには、コンテナにトランザクションの管理を任せるのではなくビーン自身がトランザクションの管理を行うことも可能です。ただし、エンティティ・ビーンではこうしたBean-Managed Transactionsは認められていません。

 Bean-Managed Transactionsには、データベースのトランザクション機能を利用するJDBCトランザクションと、Java Transaction APIの機能を利用するJTAトランザクションの2つの種類があります。どちらの方式を取るか決める必要があります。

 次の画面は、DeploytoolでBean-Managed Transactionsを指定しているところです。

画面3

画面4


 

 JDBC Transactionsの場合

 JDBC Transactionsのプログラムをするためには、javax.sql.Connectionインターフェイスの中のcommitとrollbackメソッドを利用します。次のリストを見てください。

public void ship (String productId, String orderId, int quantity) {

  try {
    con.setAutoCommit(false);
    updateOrderItem(productId, orderId);
    updateInventory(productId, quantity);
    con.commit();
  } catch (Exception ex) {
    try {
      con.rollback();
      throw new EJBException("Transaction failed: " +
        ex.getMessage());
    } catch (SQLException sqx) {
      throw new EJBException("Rollback failed: " +
        sqx.getMessage());
    }
  }
}


 

 JTA Transactionsの場合

 J2EEには、Java Transaction Service(JTS)と呼ばれるサービスが存在します。ただ、ビーンのトランザクション処理に、JTSのメソッドが、直接呼び出されることはありません。まず、JTAのメソッドが呼び出され、それがJTSの低レベルのルーチンを呼び出しています。

 JTAのトランザクションは、J2EEのトランザクション・マネージャによってコントロールされています。JTAトランザクションの境界設定のためには、UserTransactionインターフェイスのbegin、commit、rollbackメソッドが使われます。次のコードは、TellerEJBからのものですが、beginで始まりcommitで終わる2つのメソッドの呼び出しが、データベース更新のトランザクションの境界を定めています。もし、このブロック中のデータベース更新が失敗して例外が発生すれば、rollbackメソッドが呼ばれて、新しくEJBExceptionが投げられます。

public void withdrawCash(double amount) {
  UserTransaction ut = context.getUserTransaction();

  try {
    ut.begin();
    updateChecking(amount);
    machineBalance -= amount;
    insertMachine(machineBalance);
    ut.commit();
  } catch (Exception ex) {
    try {
      ut.rollback();
    } catch (SystemException syex) {
      throw new EJBException
        ("Rollback failed: " + syex.getMessage());
    }
    throw new EJBException
      ("Transaction failed: " + ex.getMessage());
  }
}

 本連載は、「J2EEは、Webとデータベースを結ぶ、サーバ・サイドのミドルウェア技術である」という観点から、J2EEの基礎を説明してきました。ここからさらに発展したい方のために、以下の参考記事を紹介して連載を終わりたいと思います。


5/5

J2EEの基礎(第8回)
  コンピューティングにおけるトランザクションの必要性
  トランザクションの基礎を知る
  J2EEのトランザクション
  トランザクション属性の特長
トランザクション属性

連載内容
J2EEの基礎
  第1回 Java Pet Storeで、J2EEを体験する(1)
  第2回 Java Pet Storeで、J2EEを体験する(2)
 

第3回 J2EEアプリケーションと配置(deployment)

  第4回 J2EEアプリケーションを構成するコンポーネント
  第5回 データベースのブラウザを作る
  第6回 EJBにおけるコンテナとコンポーネント
  第7回 J2EEのセキュリティのキホンを知る
第8回 J2EEのトランザクション処理


連載記事一覧




Java Agile フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Java Agile 記事ランキング

本日 月間