悲観もあれば楽観もある「トランザクション」の常識企業システムの常識をJBossで身につける(8)(2/4 ページ)

» 2010年04月22日 00時00分 公開
[上川伸彦, 出島宣寿, 原田壮士株式会社ビーブレイクシステムズ]

JDBCによるトランザクション処理の基礎

 まず、基本的なトランザクション処理の実装例を見ていきましょう。上記で説明した原子性を実現するためには、下記(コード1)のようにtry〜catch処理を書くことになります。

   Connection connect = null;
   Statement stmt = null;
 
   try {
       // JDBCドライバをロード
       Class.forName("oracle.jdbc.driver.OracleDriver");
       // DB接続オブジェクト
       connect = DriverManager.getConnection("jdbc:oracle:thin:〜", "scott", "tiger");
       // 自動コミット解除  …… 【1】
       connect.setAutoCommit(false);
       // ステートメントを作成
       stmt = connect.createStatement();
 
       // 処理1
       stmt.executeUpdate("UPDATE TABLE_A 〜");
       // 処理2
       stmt.executeUpdate("UPDATE TABLE_B 〜");
 
       // コミット  …… 【2】
       connect.commit();
   }
   catch (Exception e) {
       /** ログ出力 */
       try {
           // ロールバック  …… 【3】
           connect.rollback();
       }
       catch (SQLException se) {
          /** ログ出力 */
       }
   }
   finally {
       try {
           // ステートメントのクローズ
          if (stmt != null) {
               stmt.close();
           }
           // DB接続のクローズ
           if (connect != null) {
               connect.close();
           }
       }
       catch (SQLException se) {
          /** ログ出力 */
       }
   }
コード1 Javaでのデータベースアクセス

 いくつかのポイントを挙げます。

【1】自動コミットの解除

 分散トランザクションの例における、処理1と処理2を連続して行いたい場合、明示的にcommitが呼ばれるまで自動でコミットしないようにするためのフラグです。

 もし、このAutoCommitがtrueである場合、処理1と処理2はそれぞれの処理の直後に確定されてしまいます(例外が起こった場合、原子性を保つためには処理前の状態に戻す必要があるためfalseに設定します)。

【2】コミット

 一連の処理が終了した後に、すべての状態を確定するためにcommit処理(データの永続化)を行います。

【3】ロールバック

 一連の処理の途中で例外が発生したような場合に、処理1、処理2ともに変更前の状態に戻します。

ACID特性に当てはめると

 このように、一連の処理後にcommit、例外処理としてrollbackを呼び出すことで「原子性」を保証します。そのほかのACID特性の「分離性」に関しては、ConnectionオブジェクトのsetTransactionIsolationで設定できます。

 デフォルトでは、TRANSACTION_READ_COMMITTEDに設定されています。(完全に分離性を確保しようとすると、TRANSACTION_SERIALIZABLEである必要がありますがロックの影響によりパフォーマンスの問題が発生する場合があります)。

 「一貫性」は一連の処理間での整合性なので、原子性が保証されているならばアプリケーションの実装によります。

コネクションのライフサイクル

 上記の例からも分かると思いますが、JDBCのトランザクションはコネクションのライフサイクルと同じになります。つまり、コネクションが閉じられると、トランザクションも終了します。

 そのため、DAOクラスのようなものを作成し、それの複数個で1つのトランザクションを形成する場合は、コネクションを使い回す仕組みを作る必要があります。

 以上がJDBCを使用したトランザクション処理の例です。JDBCの詳細は、少し古いですが、以下の連載もご覧ください。

Javaデータアクセスの基礎
Javaからデータベースにアクセスする際の定番ミドルウェア「JDBC」を使ったデータアクセスを理解しよう

 次にJBossでのトランザクション処理について見ていきましょう。

JBossフレームワークのトランザクション

 「JBoss Transactions」は、JBossでのJTA/JTSの実装によるローカル/分散トランザクションの実現、およびXTSの実装によるWebサービストランザクションの実現をサポートしています。

Java標準の「JTA」「JTS」とは

 Java EE(J2EE)において、トランザクションを実現する手段として、「JTA(Java Transaction API)」「JTS(Java Transaction Service)」が規定されています。JTAはトランザクションを実現するためのAPI、JTSはトランザクションを管理するためのマネージャの仕様を定義したものです。

 JTAは、主に下記の3つのインターフェイスから構成されています。

javax.transaction.UserTransaction アプリケーションからトランザクションの管理を行う
javax.transaction.TransactionManager アプリケーションサーバがトランザクションの管理を行う
javax.transaction.xa.XAResource トランザクションマネージャがXA準拠のリソースマネージャと連携する
表2 JTAを構成する3つのインターフェイス

 上記の3つはインターフェイスなので、実装がないアプリケーションサーバでは、使用できません。多くの商用アプリケーションサーバやオープンソースのSeasar2などは実装を持っています。JBossも上記のインターフェイスの実装を持っています。

 JTAの特徴は、分散トランザクションをサポートしていることです。先に紹介したJDBCでも分散トランザクションは可能ですが、JTAのTransactionManagerに相当する部分を独自に制御しなければなりません。

長時間のトランザクション管理もサポートする「XTS」とは

 Webサービスのように、異なるサービス間の連携や、プロセスが多岐に渡るような場合には、単純に悲観ロックを行っては運用が成り立たないだけではなく、システム障害を引き起こす恐れがあります。そのため、Webサービスには長時間のトランザクションをサポートできる仕組みが不可欠となっています。

 JBoss Transactionsには、このような長時間のトランザクション管理もサポートするコンポーネントとして、「XTS(XML Transaction Service Component)」が規定されています。

図4 XTS概念図 図4 XTS概念図

 XTSには、サービス間のコンテキスト管理を行うベースとなるWS-C(Web Service Coodination)、WS-Cを使用するプロトコルであるWS-T(Web Service Transaction)というAPIが用意されています。

WS-C
(Web Service Coodination)
トランザクションに関係するエンティティ(=パーティシパント)の登録、およびコンテキストの管理を行う
WS-T
(Web Service Transaction)
Webサービスのトランザクション処理を定義します。図4のように、2つのモデルがサポートされており、HTTPやSOAPを介してメッセージングを行う

WS-AT(WS-Atomic Transaction)
短時間のトランザクションをサポート
WS-BA(WS-Business Activity)
時間のかかる処理をサポート。パーティシパントはリソースをロックせずにトランザクションに参加できる
表3 XTSの構成

 以上で、JBoss Transactionsを簡単に説明しました。次ページでは、JBoss Transactionsのプロジェクトを作成しサンプルを実装し始めます。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。