1。トランザクションの基本原則
Spring Transactionsの本質は、実際にはデータベースのトランザクションに対するサポートです。データベーストランザクションサポートがなければ、Springはトランザクション機能を提供できません。純粋なJDBCオペレーティングデータベースの場合、トランザクションを使用する場合は、次の手順に従うことができます。
1.接続接続を取得con = drivermanager.getConnection()
2。トランザクションを開きますcon.setautocommit(true/false);
3。crudを実行します
4。トランザクション /ロールバックトランザクションcon.commit() / con.rollback();
5。接続conn.close()を閉じます。
Springのトランザクション管理機能を使用した後、手順2と4でコードを記述することはできませんが、Spirngによって自動的に実行されます。では、Springは、私たちが書いたCRUDの前後にトランザクションをどのように開閉し、閉鎖するのでしょうか?この問題を解決することにより、Springのトランザクション管理の実装原則を全体から理解できます。例として注釈方式を簡単に紹介しましょう
1.構成ファイルの注釈ドライバーをオンにし、関連するクラスとメソッドで@Transactionalを注釈を付けて識別します。
2。スプリングが始まると、関連する豆を解析して生成します。現時点では、関連する注釈を使用してクラスと方法をチェックし、これらのクラスとメソッドのプロキシを生成し、@Transactionの関連パラメーターに基づいて関連する構成注入を実行して、関連するトランザクションがプロキシで処理されます(通常のトランザクションと例外ロールバックトランザクション)。
3。実際のデータベースレイヤーのトランザクションコミットとロールバックは、BINLOGまたはREDOログを介して実装されます。
2。スプリングトランザクションの伝播特性
Springトランザクションのいわゆる伝播属性は、スプリングが複数のトランザクションが同時に存在する場合の動作をどのように処理するかを定義します。これらのプロパティは、TransactionDefinitionで定義されています。特定の定数を次の表で説明します。
iii。データベース分離レベル
Dirty Reading: 1つのトランザクションはデータを追加、削除、および変更しますが、コミットされておらず、別のトランザクションはコミットされていないデータを読み取ることができます。この時点で最初のトランザクションがロールバックされた場合、2番目のトランザクションは汚れたデータを読み取ります。
繰り返し読み取りはありません: 1つのトランザクションで2つの読み取り操作が発生します。最初の読み取り操作と2番目の操作の間に、他のトランザクションがデータを変更します。現時点では、データの2回の読み取りは一貫していません。
ファンタジーリーディング:最初のトランザクションは、バッチの特定の範囲のデータを変更し、2番目のトランザクションはこの範囲に1つのデータを追加します。この時点で、最初のトランザクションは新しく追加されたデータの変更を失います。
要約:
分離レベルが高いほど、データの完全性と一貫性を確保できますが、同時実行のパフォーマンスへの影響が大きくなります。
ほとんどのデータベースのデフォルトの分離レベルは、SQLServerやOracleなどの委託されています
いくつかのデータベースのデフォルトの分離レベルは次のとおりです。たとえば、繰り返し読む:mysql innodb
IV。春の分離レベル
V.トランザクションのネスト
上記の理論的知識を通じて、データベーストランザクションと春のトランザクションのいくつかの属性と特性を大まかに理解しています。次に、いくつかのネストされたトランザクションシナリオを分析して、春のトランザクション伝播のメカニズムを深く理解します。
外部トランザクションサービスaのメソッドa()が内部サービスbのメソッドb()を呼び出すとします
propagation_required(springデフォルト)
serviceb.methodb()のトランザクションレベルがpropagation_requiredとして定義されている場合、servicea.methoda()が実行されると、トランザクションはすでに春に開始されています。この時点で、serviceb.methodb()が呼び出されます。 serviceb.methodb()は、servicea.methoda()のトランザクション内で実行されていることを確認し、新しいトランザクションは開始されていません。
serviceb.methodb()が実行されている場合、それ自体にトランザクションを割り当てます。
このようにして、servicea.methoda()で例外が発生した場合、またはserviceb.methodb()内の任意の場合、トランザクションはロールバックされます。
propagation_requires_new
たとえば、Servicea.Methoda()にはPropagation_Requiredのトランザクションレベルがあり、serviceb.methodb()がpropagation_requires_newのトランザクションレベルを持っていることを設計しました。
次に、serviceb.methodb()が実行されると、servicea.methoda()が配置されるトランザクションが停止され、serviceb.methodb()が新しいトランザクションを開始し、serviceb.methodb()トランザクションが完了した後も実行を続けます。
彼のトランザクションとPropagation_requiredの違いは、トランザクションのロールバックの程度です。 serviceb.methodb()は新しいトランザクションであるため、2つの異なるトランザクションがあります。 serviceb.methodb()が提出された場合、servicea.methoda()がロールバックに失敗し、serviceb.methodb()はロールバックしません。 serviceb.methodb()がロールバックに失敗した場合、servicea.methoda()によってスローされた例外がキャッチされている場合、servicea.methoda()トランザクションは引き続き送信される場合があります(主にbによってスローされる例外がロールバックされるかどうかに依存します)。
propagation_supports
serviceb.methodb()のトランザクションレベルがpropagation_supportsであると仮定すると、serviceb.methodb()に実行された場合、servicea.methoda()がトランザクションを開いたことがわかった場合、現在のトランザクションに参加します。 Servicea.Methoda()がトランザクションを開始していないことがわかった場合、トランザクション自体を開始しません。現時点では、内部メソッドの取引性は、最も外側のトランザクションに完全に依存しています。
propagation_nested
状況は今より複雑になっています。 serviceb.methodb()のトランザクションプロパティは、propagation_nestedとして構成されています。この時点で2人はどのように協力しますか? serviceb#methodbロールバックの場合、内部トランザクション(つまり、serviceb#methodb)は実行する前にsavepointにロールバックしますが、外部トランザクション(つまり、servicea#methoda)は次の2つの処理方法を持つことができます。
a。例外をキャッチし、例外ブランチロジックを実行します
void methoda(){try {serviceb.methodb(); } catch(somexception){// servicec.methodc()などの他のビジネスを実行します。 }}この方法は、ネストされたトランザクションについて最も価値のあるものでもあります。支店の実行の役割を果たします。 serviceb.methodbが失敗した場合、servicec.methodc()が実行され、serviceb.methodbが実行する前にセーブポイントに戻ってきたため、汚れたデータは生成されません(このメソッドに相当します)。この機能は、一部の特別なサービスで使用でき、Propagation_RequiredもPropagation_Requires_newもこれを行うことはできません。
b。外部トランザクションロールバック/コミットコードは、変更を加えません。内部トランザクション(serviceb#methodb)ロールバックの場合、最初のserviceb.methodbは実行する前にセーブポイントに戻り、外部トランザクション(すなわち、servicea#methoda)が特定の構成に基づいてコミットまたはロールバックのかどうかを決定します。
他の3つのトランザクション伝播属性は基本的に効果がないため、ここでは分析は行われません。
6。概要
プロジェクトでトランザクションが必要な場所については、開発者がSpringのTransactionCallbackインターフェイスを使用してトランザクションを実装する必要があることをお勧めします。 Spring Transaction Annotationsを盲目的に使用しないでください。注釈を使用する必要がある場合は、伝播メカニズムとスプリングトランザクションの分離レベルを詳細に理解する必要があります。そうしないと、予期しない影響が発生する可能性があります。