| トランザクションの自動制御 トランザクション属性 Example 例外発生時の動作 Example EJB互換のAdvice ## トランザクションの自動制御 S2Txの機能を使って、POJO(普通のJavaのクラス)に対して、Aspectでトランザクションの自動管理機能を組み込むことができます。EJBコンテナが提供するようなトランザクション管理機能をPOJOに対して透明に組み込むことができるのです。組む込むことのできるトランザクション属性は次のとおりです。 ### トランザクション属性 S2が標準で用意しているj2ee.diconには、次のトランザクション属性に対応したAdviceが定義されています。コンポーネント名がAdviceの名前です。
属性 | コンポーネント名 | 説明
--- | --- | ---
Required | `j2ee.requiredTx` | トランザクションが開始されていなければ、 自動的にトランザクションを開始します。 既にトランザクションが開始されていれば、 そのトランザクションを引き継ぎます。
RequiresNew | `j2ee.requiresNewTx` | 常に新しいトランザクションを開始させます。 既存のトランザクションが開始されているなら、 既存のトランザクションを中断し、 自分自身のトランザクションの終了後、 中断したトランザクションを復帰させます。
Mandatory | `j2ee.mandatoryTx` | トランザクションが既に開始されてなければエラーにします。
NotSupported | `j2ee.notSupportedTx` | 既存のトランザクションが開始されているなら、 既存のトランザクションを中断します。 コンポーネントのメソッドの終了後、 中断したトランザクションを復帰させます。
### Example #### Hoge.java
    package examples.tx;

    public interface Hoge {

        public void foo();
    }
#### HogeImpl.java
    package examples.tx;

    public class HogeImpl implements Hoge {

        public void foo() {
            System.out.println("foo");
        }
    }
#### HogeClient.dicon
    <components>
        <include path="j2ee.dicon"/>
        <component class="examples.tx.HogeImpl">
            <aspect>j2ee.requiredTx</aspect>
        </component>
    </components>
#### HogeClient.java
    package examples.tx;

    import org.seasar.framework.container.S2Container;
    import org.seasar.framework.container.factory.S2ContainerFactory;

    public class HogeClient {

        private static final String PATH =
            "examples/tx/HogeClient.dicon";

        public static void main(String[] args) {
            S2Container container = S2ContainerFactory.create(PATH);
            Hoge hoge = (Hoge) container.getComponent(Hoge.class);
            hoge.foo();
        }
    }
#### 実行結果
    DEBUG 2004-03-14 18:05:18,402 [main] Transaction.begin()
    foo
    DEBUG 2004-03-14 18:05:18,432 [main] Transaction.commit()
j2ee.diconはS2としてあらかじめ用意(srcの直下)されています。Adviceのコンポーネント名をaspectタグのボディに指定するだけなので簡単です。 POJOに簡単にトランザクション管理機能が組み込めることがわかってもらえたと思います。 ## 例外発生時の動作 j2ee.diconに定義されているAdviceは、コンポーネントが例外をスローした場合はトランザクションをロールバックします． 発生した例外に応じてトランザクションをコミットするかロールバックするかを指定することもできます。 Adviceの`addCommitRule(Class)`メソッドを使用すると、コンポーネントからスローされてもトランザクションをコミットする例外を指定することができます。 Adviceの`addRollbackRule(Class)`メソッドを使用すると、コンポーネントからスローされてもトランザクションをロールバックする例外を指定することができます。 コンポーネントから例外がスローされると、`addCommitRule()/addRollbackRule()`が設定された順番にマッチするかチェックされます。スローされた例外が`addCommitRule()/addRollbackRule()`で指定された例外またはその派生例外であれば、その設定に従ってトランザクションをコミットまたはロールバックします。スローされた例外が`addCommitRule()/addRollbackRule()`で指定された例外とマッチしない場合、トランザクションはロールバックされます。 ### Example #### MyTx.dicon 次の例では、実行時例外 (`java.lang.RuntimeException`) またはその派生型がスローされた場合はロールバック、例外 (`java.lang.Exception`) またはその派生型がスローされた場合はコミットするRequired のAdviceとして`myTx`を定義しています． 実行時例外 (`java.lang.RuntimeException`) は例外 (`java.lang.Exception`) の派生例外であるため、設定する順番を逆にすると実行時例外 (`java.lang.RuntimeException`) がスローされた場合でもコミットされてしまうので注意してください (Java言語のcatch節と似ています)。
    <components>
        <include path="j2ee.dicon"/>
        <component name="myTx"
            class="org.seasar.extension.tx.RequiredInterceptor">
            <initMethod name="addRollbackRule">
                <arg>@java.lang.RuntimeException@class</arg>
            </initMethod>
            <initMethod name="addCommitRule">
                <arg>@java.lang.Exception@class</arg>
            </initMethod>
        </component>
    </components>
### EJB互換のAdvice S2が標準で用意しているejbtx.diconには、EJBのコンテナ管理トランザクション (CMT) と同じように実行時例外 (`java.lang.RuntimeException`)・リモート例外 (`java.rmi.RemoteException`) とその派生例外が発生した場合はロールバックし、その他の例外 (`java.lang.Exception`) が発生した場合はコミットするAdviceが定義されています。コンポーネント名がAdviceの名前です。
属性 | コンポーネント名
--- | ---
Required | `ejbtx.requiredTx`
RequiresNew | `ejbtx.requiresNewTx`
Mandatory | `ejbtx.mandatoryTx`
NotSupported | `ejbtx.notSupportedTx`
| © Copyright The Seasar Foundation and the others 2004, all rights reserved.