3.4. Spring Boot トランザクションクライアントの使用

Spring Framework(および Spring Boot) の主な目的の 1 つとして、FIC API を簡単に使用できるようになります。すべての主要な JavaEE vanilla API は、Spring Framework(Spring Boot) に含まれています。これらは、特定の API の 代替 または 置換 ではなく、例外処理などで、より多くの設定オプションまたはより一貫した使用法を追加するラッパーです。

以下の表は、指定のブリック API を Spring 関連のインターフェイスと一致させます。

JavaEE APISpring ユーティリティー設定

JDBC

org.springframework.jdbc.core.JdbcTemplate

javax.sql.DataSource

JMS

org.springframework.jms.core.JmsTemplate

javax.jms.ConnectionFactory

JTA

org.springframework.transaction.support.TransactionTemplate

org.springframework.transaction.PlatformTransactionManager

JdbcTemplateJmsTemplate はそれぞれ javax.sql.DataSourcejavax.jms.ConnectionFactory を直接使用します。しかし、TransactionTemplatePlatformTransactionManager の Spring インターフェイスを使用します。これは、Spring が単に JavaEE を 改善する のではなく、JavaEE クライアント API を独自のものに置き換える点です。

Spring は、javax.transaction.UserTransaction を実際のシナリオでは単純すぎるインターフェイスとして扱いま s.また、javax.transaction.UserTransaction はローカルの単一のリソーストランザクションとグローバルマルチリソーストランザクションを区別せず、org.springframework.transaction.PlatformTransactionManager の実装によって開発者はより自由になります。

以下は Spring Boot の正規 API の使用例です。

// Create or get from ApplicationContext or injected with @Inject/@Autowired.
JmsTemplate jms = new JmsTemplate(...);
JdbcTemplate jdbc = new JdbcTemplate(...);
TransactionTemplate tx = new TransactionTemplate(...);

tx.execute((status) -> {
    // Perform JMS operations within transaction.
    jms.execute((SessionCallback<Object>)(session) -> {
        // Perform operations on JMS session
        return ...;
    });
    // Perform JDBC operations within transaction.
    jdbc.execute((ConnectionCallback<Object>)(connection) -> {
        // Perform operations on JDBC connection.
        return ...;
    });
    return ...;
});

上記の例では、3 種類の テンプレート はすべて簡単にインスタンス化されますが、Spring の ApplicationContext からも取得したり、@Autowired アノテーションを使用してインジェクトしたりできます。

3.4.1. Spring PlatformTransactionManager インターフェイスの使用

前述のように、javax.transaction.UserTransaction は通常 JavaEE アプリケーションの JNDI から取得されます。ただし、Spring は多くのシナリオでこのインターフェイスの明示的な実装を提供します。常に完全な JTA シナリオが必要なく、アプリケーションは単一のリソース (JDBC など) のみにアクセスする必要がある場合があります。

通常、org.springframework.transaction.PlatformTransactionManager従来のトランザクションクライアントの操作 (begincommit および rollback) を提供する Spring トランザクションクライアント API です。つまり、このインターフェイスは実行時にトランザクションの制御に必要なメソッドを提供します。

注記

トランザクションシステムのもう 1 つの重要な要素は、トランザクションリソースを実装するための API です。しかし、トランザクションリソースは通常基盤のデータベースによって実装されるため、トランザクションプログラミングのこの要素はアプリケーションプログラマーにとって懸念されることはほとんどありません。

3.4.1.1. PlatformTransactionManager インターフェイスの定義

public interface PlatformTransactionManager {

    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

    void commit(TransactionStatus status) throws TransactionException;

    void rollback(TransactionStatus status) throws TransactionException;
}

3.4.1.2. TransactionDefinition インターフェイス

TransactionDefinition インターフェイスを使用して、新規に作成されたトランザクションの特性を指定します。新規トランザクションの分離レベルおよび伝播ポリシーを指定できます。詳細は、「トランザクション伝播ポリシー」 を参照してください。

3.4.1.3. TransactionStatus インターフェイスの定義

TransactionStatus インターフェイスを使用して、現在のトランザクション (つまり、現在のスレッドに関連するトランザクション) のステータスを確認し、現在のトランザクションをロールバック用にマーク付けできます。これはインターフェイス定義です。

public interface TransactionStatus extends SavepointManager, Flushable {

    boolean isNewTransaction();

    boolean hasSavepoint();

    void setRollbackOnly();

    boolean isRollbackOnly();

    void flush();

    boolean isCompleted();
}

3.4.1.4. PlatformTransactionManager インターフェイスで定義されるメソッド

PlatformTransactionManager インターフェイスは、以下のメソッドを定義します。

getTransaction()
新しいトランザクションを作成し、新しいトランザクションの特性を定義する TransactionDefinition オブジェクトを渡すことで、それを現在のスレッドに関連付けます。これは、数多くの他のトランザクションクライアント API の begin() メソッドと似ています。
commit()
現在のトランザクションをコミットし、登録されたリソースへの保留中の変更をすべて永続化します。
rollback()
現在のトランザクションをロールバックし、登録されたリソースに対して保留中の変更をすべて取り消します。

3.4.2. トランザクションマネージャーの使用手順

通常、PlatformTransactionManager インターフェイスを直接使用しません。Apache Camel では、通常以下のようにトランザクションマネージャーを使用します。

  1. トランザクションマネージャーのインスタンスを作成します。Spring で利用できる実装がいくつかあります。「Spring Boot トランザクションクライアントの使用」を参照してください。
  2. トランザクションマネージャーインスタンスを Apache Camel コンポーネントまたはルートの transacted() DSL コマンドに渡します。トランザクションコンポーネントまたは transacted() コマンドは、トランザクションを区切るロールを果たします。詳細は、9章トランザクションを使用する Camel アプリケーションの作成 を参照してください。

3.4.3. Spring PlatformTransactionManager 実装

本セクションでは、Spring Framework で提供されるトランザクションマネージャーの実装を概説します。この実装は、ローカルトランザクションマネージャーとグローバルトランザクションマネージャーの 2 つのカテゴリーに分類されます。

Camel から開始:

  • camel-jms コンポーネントによって使用される org.apache.camel.component.jms.JmsConfiguration オブジェクトには、org.springframework.transaction.PlatformTransactionManager インターフェイスのインスタンスが必要です。
  • org.apache.camel.component.sql.SqlComponentorg.springframework.jdbc.core.JdbcTemplate クラスを内部で使用し、この JDBC テンプレートは org.springframework.transaction.PlatformTransactionManager も統合します。

ご覧のとおり、このインターフェイスの実装が いくつか 必要です。シナリオによっては、必要なプラットフォームトランザクションマネージャーを設定できます。

3.4.3.1. ローカル PlatformTransactionManager 実装

以下の一覧は、Spring Framework で提供されるローカルトランザクションマネージャーの実装をまとめています。これらのトランザクションマネージャーは 1 つのリソースのみをサポートします。

org.springframework.jms.connection.JmsTransactionManager
このトランザクションマネージャーの実装は、単一 の JMS リソースを管理できます。任意の数のキューまたはトピックに接続できますが、基礎となる JMS メッセージング製品インスタンスが同じものに所属する場合のみです。さらに、トランザクションの他のタイプのリソースを登録できません。
org.springframework.jdbc.datasource.DataSourceTransactionManager
このトランザクションマネージャーの実装では、単一 の JDBC データベースリソースを管理できます。任意の数の異なるデータベーステーブルを更新することはできますが、それらは同じ基礎となるデータベースインスタンスに属する場合に のみ 更新できます。
org.springframework.orm.jpa.JpaTransactionManager
このトランザクションマネージャーの実装は、Java Persistence API (JPA) リソースを管理できます。ただし、トランザクション内の他の種類のリソースを同時に登録できません。
org.springframework.orm.hibernate5.HibernateTransactionManager
このトランザクションマネージャーの実装は、Hibernate リソースを管理できます。ただし、トランザクション内の他の種類のリソースを同時に登録できません。さらに、JPA API はネイティブの Hibernate API よりも優先されます。

また、他に使用頻度が低い PlatformTransactionManager の実装もあります。

3.4.3.2. グローバル PlatformTransactionManager 実装

Spring Framework は、OSGi ランタイムで使用するグローバルトランザクションマネージャーの実装を 1 つ提供します。org.springframework.transaction.jta.JtaTransactionManager は、トランザクションの複数のリソースに対する操作をサポートします。このトランザクションマネージャーは XA トランザクション API をサポートし、トランザクションに複数のリソースを登録できます。このトランザクションマネージャーを使用するには、OSGi コンテナーまたはブリックサーバーにアプリケーションをデプロイする必要があります。

PlatformTransactionManager の単一リソース実装は実際の実装ですが、JtaTransactionManager は標準の javax.transaction.TransactionManager の実際の実装に対するラッパーです。

PlatformTransactionManagerJtaTransactionManager 実装は、すでに設定済みの javax.transaction.TransactionManager インスタンスや通常 javax.transaction.UserTransaction に (JNDI または CDI で) アクセスできる環境で使用するほうが適切である理由です。通常、これらの JTA インターフェイスはどちらも単一のオブジェクト/サービスによって実装されます。

JtaTransactionManager の設定/使用例は次のとおりです。

InitialContext context = new InitialContext();
UserTransaction ut = (UserTransaction) context.lookup("java:comp/UserTransaction");
TransactionManager tm = (TransactionManager) context.lookup("java:/TransactionManager");

JtaTransactionManager jta = new JtaTransactionManager();
jta.setUserTransaction(ut);
jta.setTransactionManager(tm);

TransactionTemplate jtaTx = new TransactionTemplate(jta);

jtaTx.execute((status) -> {
    // Perform resource access in the context of global transaction.
    return ...;
});

上記の例では、JTA オブジェクトの実際のインスタンス (UserTransaction および TransactionManager) が JNDI から取得されます。OSGi では、OSGi サービスレジストリーからも取得することもできます。