3.4. Spring Boot トランザクションクライアントの使用
Spring Framework(および Spring Boot) の主な目的の 1 つとして、FIC API を簡単に使用できるようになります。すべての主要な JavaEE vanilla API は、Spring Framework(Spring Boot) に含まれています。これらは、特定の API の 代替 または 置換 ではなく、例外処理などで、より多くの設定オプションまたはより一貫した使用法を追加するラッパーです。
以下の表は、指定のブリック API を Spring 関連のインターフェイスと一致させます。
JavaEE API | Spring ユーティリティー | 設定 |
---|---|---|
JDBC |
|
|
JMS |
|
|
JTA |
|
|
JdbcTemplate
と JmsTemplate
はそれぞれ javax.sql.DataSource
と javax.jms.ConnectionFactory
を直接使用します。しかし、TransactionTemplate
は PlatformTransactionManager
の 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
は 従来のトランザクションクライアントの操作 (begin
、commit
および 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 では、通常以下のようにトランザクションマネージャーを使用します。
- トランザクションマネージャーのインスタンスを作成します。Spring で利用できる実装がいくつかあります。「Spring Boot トランザクションクライアントの使用」を参照してください。
-
トランザクションマネージャーインスタンスを 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.SqlComponent
はorg.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
の実際の実装に対するラッパーです。
PlatformTransactionManager
の JtaTransactionManager
実装は、すでに設定済みの 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 サービスレジストリーからも取得することもできます。