最新の Spring アプリケーションでは、非同期実行とトランザクション動作を組み合わせるのが一般的です。ただし、Spring は非同期タスクとトランザクションを管理するため、メソッドに @Async および @Transactional(propagation = Propagation.REQUIRES_NEW) のアノテーションを付けると、予期しない動作が発生する可能性があります。
この記事では、この問題を詳しく調査し、非同期実行とトランザクション管理の両方を正しく処理するための解決策を示します。
問題: @Async と @Transactional(propagation = Propagation.REQUIRES_NEW)
次のコード スニペットを考えてみましょう:
@Async @Transactional(propagation = Propagation.REQUIRES_NEW) public void saveSomething() { // save-point one // save-point two }
一見すると、すべてが期待どおりに機能しているように見えるかもしれません。ただし、この構成には、意図しない動作を引き起こす可能性のある重要な問題がいくつかあります。
舞台裏では何が起こっているのでしょうか?
- @非同期アノテーション:
@Async アノテーションは、メソッドを別のスレッドで非同期に実行するように Spring に指示します。これは、メソッドが呼び出し元の元のスレッドでは実行されず、スレッド プール内の別のスレッドにオフロードされることを意味します。
Spring はプロキシを使用して非同期メソッドを管理します。 @Async のアノテーションが付けられたメソッドを呼び出すと、Spring は別のスレッドでメソッドを実行する内部 Executor に実行を委任します。
- @Transactional(propagation = Propagation.REQUIRES_NEW) 注釈:
@Transactional(propagation = Propagation.REQUIRES_NEW) アノテーションは、既存のトランザクションに関係なく、メソッドに対して新しいトランザクションが開始されることを保証します。呼び出しスレッド内のアクティブなトランザクションを一時停止し、メソッドの新しいトランザクションを開始します。
Spring のトランザクション管理は通常、スレッドにバインドされています。つまり、トランザクション コンテキストは現在のスレッドに関連付けられています。
紛争
この問題は、@Async が別のスレッドでメソッドを実行し、Spring のトランザクション管理がトランザクションをバインドするスレッドに依存しているために発生します。メソッドが非同期で実行されると、呼び出し元のスレッドからのトランザクション コンテキストが新しいスレッドに伝播されず、次の問題が発生します。
- @Transactional アノテーションは、非同期スレッドに新しいトランザクションを作成せず、トランザクション動作 (ロールバック、コミットなど) は正しく処理されません。
- 非同期メソッドは元のトランザクション コンテキストの外で実行されているため、REQUIRES_NEW 伝播設定は適用されません。
解決策: 非同期実行とトランザクションの分離
この問題を解決するには、トランザクションを別のサービス メソッドで処理することで、非同期実行をトランザクション ロジックから切り離します。その方法は次のとおりです:
ステップ 1: トランザクション ロジック用の新しい同期サービスを作成する
トランザクション ロジックを処理する新しいサービスを作成します。このメソッドは、トランザクション管理が期待どおりに機能することを保証するために (@Async なしで) 同期的に実行されます。ステップ 2: 同期メソッドを非同期的に呼び出す
その後、@Async を使用して、同期トランザクション メソッドを非同期的に呼び出すことができます。これにより、トランザクション ロジックがメイン スレッドで正しく処理され、非同期動作が維持されることが保証されます。
リファクタリングされたコードは次のようになります:
@Async @Transactional(propagation = Propagation.REQUIRES_NEW) public void saveSomething() { // save-point one // save-point two }
どのように機能するのでしょうか?
リファクタリングされたソリューションでは、saveSomethingAsync() メソッドに @Async の注釈を付けることで非同期実行が実現されます。これは、saveSomethingAsync() が呼び出されるとき、Spring の非同期タスク エグゼキューターによって管理される別のスレッドで実行されることを意味します。これを別のスレッドで実行すると、メインスレッドは saveSomethingAsync() が完了するのを待たずに実行を継続できます。このアプローチは、長時間実行されるタスクをオフロードしたり、応答性を向上させたり、独立した操作を同時に処理したりするシナリオに有益です。
トランザクション動作の場合、TransactionalService の saveSomething() メソッドには @Transactional(propagation = Propagation.REQUIRES_NEW) の注釈が付けられます。これにより、saveSomething() を呼び出すたびに、呼び出しメソッド内の既存のトランザクションから独立して新しいトランザクションが作成されるようになります。 REQUIRES_NEW 伝播は新しいトランザクションを開始し、既存のトランザクションを一時停止します。これにより、saveSomething() が分離されたトランザクション コンテキストで動作できるようになります。これは、元の呼び出しメソッドにトランザクションがある場合でも、saveSomething() は独自の別のトランザクション内で動作し、この操作に対してのみ制御されたコミットとロールバックが有効になることを意味します。
非同期実行をトランザクション ロジックから切り離すことで、トランザクション管理が期待どおりに機能することを保証します。この設定では、トランザクション コンテキストは saveSomething() メソッド内で正しく処理されたままですが、saveSomethingAsync() メソッドは別のスレッドで実行され続けます。この懸念の分離により、非同期処理と信頼性の高いトランザクション管理の両方の利点が得られ、同時に処理する場合でも独立した安全なデータ操作が可能になります。
このアプローチをいつ使用するか?
トランザクションの分離が重要な場合: 特定の操作が別のトランザクション (つまり REQUIRES_NEW) で実行されるようにする必要がある場合、このアプローチはうまく機能します。
非同期操作: 非同期で実行する必要があるが、独自のトランザクション境界も必要とする、長時間実行される独立したタスクがある場合。
代替案: メッセージ キューを使用して完全な分離を行う
より高度な分離が必要な場合、または再試行、エラー処理、長時間実行プロセスを処理したい場合は、タスクを Kafka や RabbitMQ などのメッセージ キューにオフロードすることを検討してください。メッセージ キューを使用すると、各タスクが独自のコンテキストで実行され、トランザクションを独立して管理できるようになります。
以上がSpring でのトランザクションによる非同期実行の処理: よくある落とし穴とその解決方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

Javaはプラットフォーム固有の問題をどのように軽減しますか? Javaは、JVMおよび標準ライブラリを通じてプラットフォームに依存します。 1)bytecodeとjvmを使用して、オペレーティングシステムの違いを抽象化します。 2)標準のライブラリは、パスクラス処理ファイルパス、CHARSETクラス処理文字エンコードなど、クロスプラットフォームAPIを提供します。 3)最適化とデバッグのために、実際のプロジェクトで構成ファイルとマルチプラットフォームテストを使用します。

java'splatformentencentenhancesmicroservicesecturectureby byofferingdeploymentflexability、一貫性、スケーラビリティ、およびポート可能性。1)展開の展開の展開は、AllosmicRoserviThajvm.2)deploymentflexibility lowsmicroserviceSjvm.2)一貫性のあるAcrossServicessimplisimpligiessdevelisementand

Graalvmは、Javaのプラットフォームの独立性を3つの方法で強化します。1。言語間の相互運用性、Javaが他の言語とシームレスに相互運用できるようにします。 2。独立したランタイム環境、graalvmnativeimageを介してJavaプログラムをローカル実行可能ファイルにコンパイルします。 3.パフォーマンスの最適化、Graalコンパイラは、Javaプログラムのパフォーマンスと一貫性を改善するための効率的なマシンコードを生成します。

aeffectivelytestjavaapplicationsforformcompativity、followthesesteps:1)setupautomatedacrossmultipleplatformsusingsingcitoolslikejenkinsorgithubactions.2)divivisonmanualtingonrealhardwaretocatissusuessususus.3)

Javaコンパイラは、ソースコードをプラットフォームに依存しないバイトコードに変換することにより、Javaのプラットフォームの独立性を実現し、JVMがインストールされた任意のオペレーティングシステムでJavaプログラムを実行できるようにします。

bytecodeachievesplatformedentencedexedectedbyavirtualMachine(VM)、forexApplev.forexample、javabytecodecanrunrunrunnonydevicewithajvm、writeonce、runany "ferfuctionality.whilebytecodeOffersenhの可能性を承認します

Javaは100%のプラットフォームの独立性を達成することはできませんが、そのプラットフォームの独立性はJVMとBytecodeを通じて実装され、コードが異なるプラットフォームで実行されるようにします。具体的な実装には、次のものが含まれます。1。bytecodeへのコンパイル。 2。JVMの解釈と実行。 3。標準ライブラリの一貫性。ただし、JVMの実装の違い、オペレーティングシステムとハードウェアの違い、およびサードパーティライブラリの互換性は、プラットフォームの独立性に影響を与える可能性があります。

Javaは、「Write onse、Averywhere」を通じてプラットフォームの独立性を実現し、コードの保守性を向上させます。 2。メンテナンスコストが低いため、1つの変更のみが必要です。 3.チームのコラボレーション効率が高く、知識共有に便利です。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

SecLists
SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

AtomエディタMac版ダウンロード
最も人気のあるオープンソースエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ZendStudio 13.5.1 Mac
強力な PHP 統合開発環境

ホットトピック









