この記事では、Springのトランザクション管理に関する詳細な調査を実施します。主に、 @Transactionalが下部でどのように機能するかを紹介します。次の記事では、次のように紹介します。
伝播(トランザクション伝播)や分離(分離)などの属性の使用
トランザクションの使用の落とし穴とそれを回避する方法は何ですか
JPAおよびトランザクション管理
JPA自体がいかなる宣言的トランザクション管理も提供しないことが重要です。依存関係噴射コンテナの外側でJPAを使用する場合、開発者がトランザクションをプログラム的に実装する必要があります。
userTransaction utx = entitymanager.getTransaction(); try {utx.begin(); businessLogic(); utx.commit();} catch(exception ex){utx.rollback(); shrowex;}このトランザクション管理方法により、トランザクションスコープをコードで明確に表現できますが、次の欠点があります。
繰り返されるコードとエラーは存在しやすいです
エラーは大きな影響を与える可能性があります
エラーをデバッグして再現することは困難です
コードベースの可読性を低下させます
メソッドが他のトランザクションメソッドを呼び出す場合はどうなりますか?
Spring @Transactionalを使用します
spring @Transactionalを使用すると、上記のコードが簡素化されています。
@transactional publicvoid businesslogic(){...トランザクション内でエンティティマネージャーを使用...}}コードはより簡潔で読みやすく、現在春に推奨される方法でもあります。
トランザクション伝播などの多くの重要な側面は、 @Transactionalを使用して自動的に処理できます。この場合、BusinessLogic()が別のトランザクションメソッドを呼び出す場合、メソッドはオプションに基づいて実行中のトランザクションに参加する方法を決定します。
この強力なメカニズムの潜在的な欠点の1つは、基礎となる操作を隠し、適切に機能しない場合はデバッグが困難であることです。
@transactionalの意味
@Transactionalの重要なポイントの1つは、2つの別々の概念を考慮することです。どちらも独自の範囲とライフサイクルを持っています。
永続性コンテキスト(永続性コンテキスト)
データベーストランザクション
@Transactional自体は、単一のトランザクションの範囲を定義します。このトランザクションは、永続性コンテキストの範囲内です。
JPAの永続性コンテキストはEntityManagerであり、内部実装はHibernateセッションを使用します(HibernateをPersistence Providerとして使用)。
永続性コンテキストは、有限コレクションのJavaオブジェクトの状態を記録し、これらのオブジェクトの変更が最終的にデータベースに持続することを保証する単なる同期オブジェクトです。
これは、単一のトランザクションとは非常に異なる概念です。エンティティマネージャーは複数のトランザクションで使用でき、実際にこの方法で使用されます。
EntityManagerはいつ複数のトランザクションに及びますか?
最も一般的な状況は、アプリケーションがビューモードでオープンセッションを使用して、怠zyな初期化の例外を処理する場合です。以前の記事では、このアプローチの利点と短所を導入しました。
この場合、ビューレイヤーによって実行される複数のクエリは、単一のトランザクションビジネスロジックではなく、個別のトランザクションにありますが、これらのクエリは同じエンティティマネージャーによって管理されます。
別のシナリオは、開発者がPersistenceContextType.extendedとして永続性コンテキストをマークすることです。つまり、複数のリクエストに応答できることを意味します。
EntityManagerとトランザクションの関係を定義する方法は?
これはアプリケーション開発者によって選択されますが、JPAエンティティマネージャーにとって最も一般的な方法は「アプリケーショントランザクションごとのエンティティマネージャー」モードです。エンティティマネージャーの注入の一般的な方法は次のとおりです。
@persistencontext privateentitymanager em;
デフォルトは「トランザクションごとのエンティティマネージャー」モードです。このモードでは、エンティティマネージャーが@transactionalメソッド内で使用される場合、メソッドは単一のトランザクションで実行されます。
@persistenceContextはどのように機能しますか?
以下の問題は、@PerSistenceContextがエンティティマネージャーが起動したときにのみエンティティマネージャーを挿入する方法です。エンティティマネージャーのライフサイクルが短く、要求ごとに複数のエンティティマネージャーが必要であると仮定します。
答えはできないということです。EntityManagerはインターフェイスであり、Spring Beanに注入されるのはエンティティマネージャー自体ではなく、実行時の特定のエンティティマネージャーのコンテキスト認識プロキシ(コンテキスト認識プロキシ)です。
プロキシに一般的に使用される特定のクラスは、sharedentitymanagerinvocationhandlerであり、デバッガーの助けを借りて確認できます。
では、@Transactionalはどのように機能しますか?
EntityManagerインターフェイスを実装する永続的なコンテキストプロキシは、宣言的トランザクション管理の唯一の部分ではなく、実際には3つのコンポーネントが含まれています。
EntityManagerプロキシ自体
トランザクションのセクション
トランザクションマネージャー
これらの3つの部分とその相互作用を見てください。
トランザクションのセクション
トランザクションセクションは、注釈付きのビジネス方法の前後に呼び出すことができる「周り」セクションです。セクションを実装する特定のクラスは、TransactionInterceptorです。
トランザクションのセクションには2つの主な責任があります。
「前」では、このセクションでは、呼び出されたビジネス方法が進行中のトランザクションの範囲内で実行されるか、新しい独立したトランザクションを開始するかどうかを決定するコールポイントを提供します。
「After」では、このセクションでは、トランザクションがコミットされている、ロールバック、または実行され続けていることを判断する必要があります。
「前」では、トランザクションセクション自体には決定ロジックが含まれておらず、新しいトランザクションを開始する決定は、完了のためにトランザクションマネージャーに委任されます。
トランザクションマネージャー
トランザクションマネージャーは、次の2つの問題を解決する必要があります。
新しいエンティティマネージャーを作成する必要がありますか?
新しいトランザクションを開始する必要がありますか?
これらには、「前」のロジックが呼び出されたときに、トランザクションセクションを決定する必要があります。トランザクションマネージャーの決定は、次の2つのポイントに基づいています。
トランザクションは進行中です
トランザクション方式の伝播プロパティ(たとえば、必要なのは常に新しいトランザクションを開始します)
トランザクションマネージャーが新しいトランザクションを作成したいと判断した場合、次のようになります。
1.新しいエンティティマネージャーを作成します
2。IntityManagerは現在のスレッドにバインドされています
3.データベース接続プールから接続を取得します
4.現在のスレッドへの接続をバインドします
ThreadLocal変数を使用して、エンティティマネージャーとデータベース接続の両方を現在のスレッドにバインドします。
トランザクションは、スレッドに保存されているときに実行され、それらが使用されなくなった場合、トランザクションマネージャーはそれらをクリアするかどうかを決定します。
現在のエンティティマネージャーとデータベース接続が必要な場合、プログラムの一部をスレッドから取得できます。
EntityManagerプロキシ
EntityManager Proxy(既に以前に導入されています)は、パズルの最後の部分です。ビジネスメソッドがEntityManager.Persist()を呼び出す場合、これはエンティティマネージャーから直接呼び出されません。
代わりに、ビジネスメソッドはエージェントを呼び出し、スレッドから現在のエンティティマネージャーを取得します。前述のように、トランザクションマネージャーはエンティティマネージャーをスレッドにバインドします。
@Transactionalメカニズムのさまざまな部分を理解した後、それを実装する一般的に使用されるスプリング構成を見てみましょう。
3つの部分を統合します
トランザクションアノテーションが正しく機能できるように3つの部分を組み合わせる方法は?最初にエンティティマネージャーファクトリーを定義します。
これにより、Persistence Context Annotationでエンティティマネージャーのプロキシを挿入できます。
@configuration publicClass EntityManagerFactoryConfiguration {@autowired privatedataSource dataSource; @bean(name = "entitymanagerfactory")publiclocalcontainerentitymanagerfactorybean emf(){localcontainerentitymanagerfactorybean emf = ... emf.setDataSource(dataSource); emf.setPackagestoscan(NewsTring [] {"your.Package"}); emf.setJPavendoradapter(newHiberNateJPavendOradapter(); RecortineMf;}}}}次のステップは、トランザクションマネージャーを構成し、クラスの注釈付き@Transactionalのトランザクションファセットを適用することです。
@configuraturation @enabletransactionmanagement publicclass transactionmanagersconfig {@autowired entitymanagerfactory emf; @autowired privatedatasource datasource; @bean(name = "transactionmanager")publicplatformtransactionmanager transactionmanager(){jpatransactionmanager tm = newjpatransactionManager(); tm.setEntityManagerFactory(emf); tm.setDataSource(dataSource); returnm;}}}annotation @enabletransactionmanagementは、 @Transactionalによって注釈が付けられたクラスがトランザクションの削減に囲まれていることをSpringに通知します。この方法で@Transactionalを使用できます。
要約します
Springの宣言的トランザクション管理メカニズムは非常に強力ですが、誤用または簡単に構成されたエラーを構成することができます。
このメカニズムなどの問題が適切に機能しない場合、または予想される動作結果を達成できない場合、その内部作業を理解することが役立ちます。
覚えておくべき最も重要なことは、2つの概念を考慮することです。トランザクションと永続性のコンテキストで、それぞれが読みにくいライフサイクルを持つそれぞれです。
上記は、Spring @Transactionalの実用的な原則に関するこの記事のすべての内容です。私はそれが誰にでも役立つことを願っています。興味のある友人は、このサイトの他の関連トピックを引き続き参照できます。欠点がある場合は、それを指摘するためにメッセージを残してください。このサイトへのご支援をありがとうございました!