ホームページ  >  記事  >  php教程  >  Springトランザクションの抽象化

Springトランザクションの抽象化

高洛峰
高洛峰オリジナル
2016-11-22 15:17:071158ブラウズ

1 Spring Framework トランザクション管理の概要

包括的なトランザクション サポートは、Spring Framework を使用する説得力のある理由です。 Spring フレームワークは、トランザクション管理に一貫した抽象化を提供し、次のような利点があります:

Java Transaction API (JTA)、JDBC、Hibernate、Java Persistence API (JPA)、Java Data Objects ( JDO など) など、さまざまなトランザクション API 全体で一貫したプログラミング モデル)。

宣言型トランザクション管理をサポートします。

複雑なトランザクション API (JTA など) よりも単純です。

Spring のデータアクセス抽象化と完全に統合されています。

Spring Framework のトランザクション サポート モデルの 2 つの利点

従来、Java EE 開発者には、グローバル トランザクションとローカル トランザクションという 2 つのオプションのトランザクション管理方法があり、それぞれに独自の制限がありました。

2.1 グローバル トランザクション

グローバル トランザクションを使用すると、複数のトランザクション リソース (通常はリレーショナル データベースとメッセージ キュー) を使用できます。このアプリケーションは、扱いにくい API である JTA を介してグローバル トランザクションを管理します。また、JTA UserTransaction は通常、JNDI から取得する必要があります。つまり、JNDI を使用する必要があります。 JTA は通常、アプリケーション サーバー環境でのみ使用できるため、グローバル トランザクションを使用すると、アプリケーション コードの再利用が制限されることは明らかです。

これまで、グローバル トランザクションを使用する好ましい方法は、EJB CMT (コンテナ管理トランザクション) を使用することでした。CMT は宣言型トランザクション管理です。 EJB CMT は関連トランザクションの JNDI ルックアップをクリアしますが、EJB 自体は JNDI を使用する必要があります。これにより、トランザクションを制御するための Java コードを記述する必要性がほとんど (すべてではありません) なくなります。重要な欠点は、CMT が JTA とアプリケーション サーバー環境をバンドルしていることです。同時に、EJB を使用してビジネス ロジックを実装する場合、または少なくともトランザクション EJB ファサード内でのみ機能します。

2.2 ローカル トランザクション

ローカル トランザクションは特定のリソースです。たとえば、トランザクションは JDBC 接続に関連付けられます。ローカル トランザクションは使いやすいですが、複数のトランザクション リソースにまたがることができないという重大な欠点があります。たとえば、JDBC 接続を使用して管理されるトランザクションは、グローバル JTA トランザクション内で実行できません。アプリケーション サーバーはトランザクション管理を担当しないため、リソース全体にわたる正確性は保証されません。もう 1 つの欠点は、ローカル トランザクションの煩わしいプログラミング モデルです。

2.3 Spring フレームワークの一貫したプログラミング モデル

Spring は、グローバル トランザクションとローカル トランザクションの欠点を解決します。これにより、開発者はどの環境でも一貫したプログラミング モデルを使用できます。開発者は独自のコードを記述するだけで済み、異なる環境での異なるトランザクション管理が抽象化されます。 Spring フレームワークは、宣言型およびプログラムによるトランザクション管理を提供します。ほとんどのユーザーは宣言型トランザクション管理を好みますが、これも推奨されます。

プログラムによるトランザクション管理を使用することで、開発者は Spring Framework のトランザクション抽象化を使用し、基になるあらゆるトランザクションで実行できます。推奨される宣言型モデルを使用すると、開発者は通常、トランザクション管理コードをほとんどまたはまったく記述しないため、Spring Framework トランザクション API や他のトランザクション API に依存しません。

3 Spring フレームワークのトランザクション抽象化を理解するための鍵

Spring トランザクション抽象化は、トランザクション戦略の概念です。トランザクション戦略は、 org.springframework.transaction.PlatformTransactionManager インターフェイスを通じて定義されます:

public Interface PlatformTransactionManager {

TransactionStatus getTransaction(

using using using org.springframework.transaction. ‐ ‐ ‐‐‐‐‐‐‐‐ ‐‐ void commit(TransactionStatus status) throws TransactionException;

void rollback(TransactionStatus status) throws TransactionException;

}

これは主にサービス プロバイダー インターフェイス (SPI) ですが、コード内でプログラミング モデルを使用することもできます。 。 PlatformTransactionManager はインターフェイスであるため、モックやスタブ化が簡単です。 JNDI のような検索戦略は必要ありません。 PlatformTransactionManager は、Spring IoC コンテナーで定義された他のオブジェクトと同様に実装されます。この利点により、JTA を使用する場合でも Spring Framework トランザクションを抽象化する価値があります。トランザクション コードは、JTA を直接使用するよりもテストが簡単です。

PlatformTransactionManager インターフェース メソッドによってスローされる TransactionException は、検出されない例外です (つまり、java.lang.RuntimeException を継承します)。トランザクションの失敗は致命的です。アプリケーション コードがトランザクションの失敗から実際に回復できるまれなケースでは、アプリケーション開発者は TransactionException をキャッチして処理することを選択できます。利点は、開発者がこれを行う必要がないことです。

getTransaction(..) メソッドは、TransactionDefinition パラメーターに依存して TransactionStatus オブジェクトを返します。返された TransactionStatus は、新しいトランザクションを表すことも、一致するトランザクションが現在のコール スタックに存在する場合は既存のトランザクションを表すこともできます。実際、これは後者のケースです。Java EE トランザクション コンテキストと同様に、TransactionStatus は実行可能なトランザクションに関連付けられます。

TransactionDefinition インターフェースの説明:

分離 (トランザクション分離レベル): トランザクション分離レベル。たとえば、このトランザクションは他のコミットされていないトランザクションを読み取ることができますか?

Propagation (トランザクションの伝播): 通常、トランザクション スコープで実行されるすべてのコードはトランザクション内で実行されます。ただし、トランザクション コンテキストがすでに存在する場合、トランザクション メソッドの実行の動作を指定するオプションがあります。たとえば、コードは既存のトランザクションで実行を継続することも (通常の状況)、既存のトランザクションを一時停止して新しいトランザクションを作成することもできます。

トランザクション タイムアウト: トランザクションが期限切れになり、基礎となるトランザクションを通じて自動的にロールバックされるまでのトランザクションの実行時間。

読み取り専用状態: 読み取り専用トランザクションは、コードがデータを読み取るだけでデータを変更しない場合に使用できます。場合によっては、たとえば Hibernate を使用する場合など、読み取り専用トランザクションが最適化に有益です。

これらの設定は、標準的なトランザクションの概念を反映しています。これらの基礎となる概念は、Spring Framework またはトランザクション管理ソリューションの使用に不可欠です。 transactionStatusインターフェイスは、トランザクションコードが実行可能なトランザクションとクエリトランザクションステータスを制御する簡単な方法を提供します。

void setRollbackOnly();

boolean isRollbackOnly();

void flash();

boolean isCompleted(); Spring で宣言型とプログラム型のどちらを選択するかは、プラットフォームのトランザクション管理にとって不可欠です。正しい PlatformTransactionManager 実装を定義します。通常、この実装は依存関係の注入を通じて定義します。

PlatformTransactionManager は通常、JDBC、JTA、Hibernate などの作業環境を知る必要があります。以下は、ローカルの PlatformTransactionManager を定義する例です。

JDBC データソースを定義します:

Destroy-method="close"> value="${jdbc.driverClassName}" />

;bean id="txManager"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

Java EE コンテナーで JTA を使用している場合は、JNDI と Spring の JtaTransactionManager を使用してコンテナーの DataSource を取得できます:

< ;beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:jee= "http ://www.springframework.org/schema/jee" /beans/spring-beans.xsd

;

JtaTransactionManager はコンテナのグローバル トランザクション管理を使用するため、DataSource や特定のリソースについて知る必要はありません。

Hibernate のローカル トランザクションを使用することもできます。この場合、Hibernate の LocalSessionFactoryBean を定義する必要があります。アプリケーション コードはこれを使用して Hibernate Session インスタンスを取得します。

この場合、txManager Bean は HibernateTransactionManager です。 DataSourceTransactionManager が DataSource を参照する必要があるのと同様に、HibernateTransactionManager は SessionFactory を参照する必要があります。

org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml

hibernate.dialect=${hibernate.dialect}

結果次第では Hibernate と Java EE コンテナ管理の JTA 事务、那么你のみ JtaTransactionManager を使用します:

在これらすべての状況において、アプリケーションのコードを変更する必要はありません。ただ、ジグの管理方法を変更するために構成を変更する必要があります。链接必要同步事务

4.1 の高レベルの同期方式

の最初の方法は、永続化された API をベースにした Spring の高レベルのモジュールを使用するか、バンドル付きのローカル OR を使用することです。 M API——感知これらのことは、リソースの作成、再利用、消去、リソースの選択、およびエマージェンシーを処理する方法案内部を理解している。板式持久化逻辑通常、ローカル ORM API を使用するか、JdbcTemplate 取得モジュールを使用します。

4.2 低レベルの同時実行方式

例: DataSourceUtils (JDBC)、EntityManagerFactoryUtils (JPA)、SessionFactoryUtils (Hibernate)、PersistenceManagerFactoryU tils(JDO)には底層同時方式が存在します。アプリケーションプログラムのコードは、直接処理するために、Spring フレーム管理を確保するこれらの種類の例を使用して、プロセス中に発生する常に正確なマッピング一致性 API を(選択的に)使用します。 JDBC の場合、JDBC 方式では DataSource 上で getConnection() メソッドを使用し、Spring の org.springframework.jdbc.datasource.DataSourceUtils:

Connection conn = DataSourceUtils.getConnection(dataSource);

の結果が存在します。オブジェクトに接続が確立されており、サンプルが返されます。その場合、メソッドは、(任意で) 既存の接続を確立し、その後同じ接続で繰り返し使用するように制御されます。 Spring 管理を必要としない (事の同時実行は選択可能) ため、Spring 管理を使用するかどうかに関係なく、すべてのユーザーがこれを使用できます。 DataSourceUtils またはその他のヘルプ クラスを使用してください。

4.3 TransactionAwareDataSourceProxy

最下層には、すでに TransactionAwareDataSourceProxy クラスが存在します。 Java EE サーバーが提供するトランスポートに似ていますJNDI DataSource。

5 注意事項管理

Spring フレームの注意事項管理 Spring 面方向切面コード (AOP) が可能になっていますが、Spring フレームはモジュール形式でパケットを配布するため、AOP を理解する必要があります。

5.1 Spring フレームワークの説明書式が実行されることを理解します。

要素データによる駆動ジグ通知 (現在は XML または注釈ベース) を介して実行されます。AOP 結合ジジタル要素データは AOP エージェントを生成し、TransactionInterceptor を使用して適切に結合される PlatformTransactionManager を実行します。駆動物事のプロセスを調整するために使用されます。

5.2 宣言型トランザクションの実装例

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx = "http://www.springframework.org/schema/tx"

/www.springframework.org/schema/aop

http://www.springframework.org/schema/aop /spring-Aop.xsd"> ;

& lt;! ;tx:advice id="txAdvice"transaction-manager="txManager">

tx:method name="get*" read-only="true " />" execution(* x.y.service.fooservice。*(..)) " /&gt; &gt;

&lt;プロパティ名= "driverclassname" value = "oracle.jdbc.driver.oracledriver"/>;

,,,,, "&gt; ,,,,,、ランタイム時にスプリングトランザクションロールバックを引き起こします例外またはエラーがスローされます。チェックされた例外によって Spring トランザクションがロールバックされることはありません。

トランザクション ロールバックの例外タイプを明示的に構成できます。

5.4 Bean ごとに異なるトランザクション セマンティクスを設定する

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http:/ /www .springframework.org/schema/aop "/beans

schema/tx/spring-tx。 ..))"/>

;

アドバイザー pointcut-ref="noTxServiceOperation" butes>

&lt;/tx:属性&g;タイムアウトはサポートされていません

どの RuntimeException もロールバックをトリガーしますが、チェック例外はトリガーされません

内にネストされているさまざまな タグを変更できます。 ;tx:attributes/> タグのプロパティ:

5.6 @Transactional

の使用

注釈管理を有効にする:

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx=" http ://www.springframework.org/schema/tx" beans/spring-beans.xsd

.springframework.org /schema/aop

http://www.springframework.org/schema/aop/spring-aop。 xsd">

& lt; ---- & gt;

;

宣言アノテーション:

@Transactional

public class DefaultFooServiceimplements FooService {

Foo ( String fooName);

Foo getFoo(String fooName, String barName);

void insertFoo(Foo foo) ;

void updateFoo(Foo foo);

}

@トランザクション設定:

@Transactionalのマルチトランザクションマネージャー:

public class TransactionalService {

@Transactional("order" ; />

class="org. springframework.jdbc.datasource.DataSourceTransactionManager">

...

Springトランザクションの抽象化

class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> ;

...

カスタム略語アノテーション

@Target({ElementType.METHOD, ElementType.TYPE})

@Retention (RetentionPolicy.RUNTIME)

@Transactional("order")

public @interface OrderTx {

}

@Target({ElementType.METHOD, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Transactional("account")

public @interface AccountTx {

}

5.7 トランザクションの伝播

PROPAGATION_REQUIRED

トランザクションの伝播を PROPAGATION_REQUIRED に設定すると、メソッドごとに論理トランザクション スコープが作成されます。各論理トランザクション スコープはロールバック状態を独立して決定でき、外側のトランザクション スコープのロジックは内側のトランザクション スコープから独立しています。もちろん、標準の PROPAGATION_REQUIRED の場合、これらすべてのスコープは同じ物理トランザクションにマップされます。したがって、内部トランザクション スコープでロールバック フラグを設定するだけでは、発生する外部トランザクションの実際のコミットには影響しません。

ただし、この場合、内部トランザクション スコープはロールバック マークのみに設定されており、外部トランザクションはロールバックを決定していないため、ロールバックは予期せぬものになります。対応する UnexpectedRollbackException がスローされます。

PROPAGATION_REQUIRES_NEW

PROPAGATION_REQUIRED と比較して、PROPAGATION_REQUIRES_NEW は完全に独立したトランザクションを使用します。この場合、基礎となる物理トランザクションは異なるため、独立してコミットまたはロールバックでき、外部トランザクションのロールバック ステータスは内部トランザクションの影響を受けません。

PROPAGATION_NESTED

複数のセーブポイントにロールバックできる物理トランザクションを使用します。このロールバックにより、内部トランザクション スコープがそのスコープのロールバックをトリガーできるようになり、一部の操作がロールバックされた場合でも、外部トランザクションは物理トランザクションを継続できるようになります。この設定は通常、JDBC セーブポイントにマップされるため、JDBC リソース トランザクションにのみ使用できます。

6も同様です。

public class SimpleService は Service {

private Final TransactionTemplatetransactionTemplate;

public SimpleService(PlatformTransactionManagertransactionManager) {

Assert.notNull(transactionManager, "「Manager」引数は null であってはなりません。"); R this.TRANSACTIONTEMPLATE = 新しい TransactionTemplate (TransactionManager)

}

E.Execute (New TransactionCallback () {

Public Object Dointransaction (TransactionStatus ステータス) {

UpdateOperation1 ( );

戻るresultOfUpdateOperation2(); 結果クラス:

transactionTemplate.execute(new TransactionCallbackWithoutResult() {

protected void doInTransactionWithoutResult(TransactionStatus status) {

(new TransactionCallbackWithoutResult() {

T ProteCted Void DointransactionWithoutResult (TransactionStatus ステータス) {

{

UpdateOperation1 (); Sexepting ex) {

status.setrolllLLLLLLY ();

}}}

});

public class SimpleServiceimplements Service {

プライベートFinal TransactionTemplatetransactionTemplate;

public SimpleService(PlatformTransactionManagertransactionManager) {

Assert.notNull(transactionManager, "「transactionManager」引数は null であってはなりません。");

this.transactionTemplate = new TransactionTemplate(transactionManager);

this.transactionTemplate.setIsolationLevel(

TransactionDefinition.ISOLATION_READ_UNCOMMITTED);

this .transactionTemplate.setTimeout(30); // 30 秒

}

}

Spring XML を使用して TransactionTemplate を構成します。

class="org.springframework.transaction.support.TransactionTemplate">

6.2 PlatformTransactionManager の使用

DefaultTransactionDefinition def = new DefaultTransactionDefinition();

def.setName("SomeTxName");

def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatus status = txManager.getTransaction(def);

try {

/ / ビジネス ロジックを実行します

} catch (MyException ex) {

txManager.rollback(status);

throw ex;

}

txManager.commit(status);

7 トランザクションのプログラム管理または宣言型管理を選択しますか?

トランザクション操作の数が少ない場合は、プログラムによるトランザクション管理を選択してください。

8 トランザクション バインディング イベント

Spring 4.2 以降、リスナー イベントをトランザクション フェーズにバインドできるようになりました。

@Component public class MyComponent {

@TransactionalEventListener

public void handleOrderCreatedEvent(CreationEvent CreationEvent) {

}

TransactionalEventListener アノテーションは、カスタマイズされたリスニング トランザクション ステージを可能にするフェーズ属性を公開します。有効なフェーズは、BEFORE_COMMIT、AFTER_COMMIT (デフォルト)、AFTER_ROLLBACK、および AFTER_COMPLETION です。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。