ホームページ Java &#&チュートリアル Spring でのトランザクションによる非同期実行の処理: よくある落とし穴とその解決方法

Spring でのトランザクションによる非同期実行の処理: よくある落とし穴とその解決方法

Nov 09, 2024 am 06:42 AM

Handling Asynchronous Execution with Transactions in Spring: A Common Pitfall and How to Solve It

最新の 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() が完了するのを待たずに実行を継続できます。このアプローチは、長時間実行されるタスクをオフロードしたり、応答性を向上させたり、独立した操作を同時に処理したりするシナリオに有益です。

トランザクション動作の場合、TransactionalServicesaveSomething() メソッドには @Transactional(propagation = Propagation.REQUIRES_NEW) の注釈が付けられます。これにより、saveSomething() を呼び出すたびに、呼び出しメソッド内の既存のトランザクションから独立して新しいトランザクションが作成されるようになります。 REQUIRES_NEW 伝播は新しいトランザクションを開始し、既存のトランザクションを一時停止します。これにより、saveSomething() が分離されたトランザクション コンテキストで動作できるようになります。これは、元の呼び出しメソッドにトランザクションがある場合でも、saveSomething() は独自の別のトランザクション内で動作し、この操作に対してのみ制御されたコミットとロールバックが有効になることを意味します。

非同期実行をトランザクション ロジックから切り離すことで、トランザクション管理が期待どおりに機能することを保証します。この設定では、トランザクション コンテキストは saveSomething() メソッド内で正しく処理されたままですが、saveSomethingAsync() メソッドは別のスレッドで実行され続けます。この懸念の分離により、非同期処理と信頼性の高いトランザクション管理の両方の利点が得られ、同時に処理する場合でも独立した安全なデータ操作が可能になります。

このアプローチをいつ使用するか?

  • トランザクションの分離が重要な場合: 特定の操作が別のトランザクション (つまり REQUIRES_NEW) で実行されるようにする必要がある場合、このアプローチはうまく機能します。

  • 非同期操作: 非同期で実行する必要があるが、独自のトランザクション境界も必要とする、長時間実行される独立したタスクがある場合。

代替案: メッセージ キューを使用して完全な分離を行う

より高度な分離が必要な場合、または再試行、エラー処理、長時間実行プロセスを処理したい場合は、タスクを Kafka や RabbitMQ などのメッセージ キューにオフロードすることを検討してください。メッセージ キューを使用すると、各タスクが独自のコンテキストで実行され、トランザクションを独立して管理できるようになります。

以上がSpring でのトランザクションによる非同期実行の処理: よくある落とし穴とその解決方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

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

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

会社のセキュリティソフトウェアはアプリケーションの実行に失敗していますか?それをトラブルシューティングと解決する方法は? 会社のセキュリティソフトウェアはアプリケーションの実行に失敗していますか?それをトラブルシューティングと解決する方法は? Apr 19, 2025 pm 04:51 PM

一部のアプリケーションが適切に機能しないようにする会社のセキュリティソフトウェアのトラブルシューティングとソリューション。多くの企業は、内部ネットワークセキュリティを確保するためにセキュリティソフトウェアを展開します。 ...

名前を数値に変換してソートを実装し、グループの一貫性を維持するにはどうすればよいですか? 名前を数値に変換してソートを実装し、グループの一貫性を維持するにはどうすればよいですか? Apr 19, 2025 pm 11:30 PM

多くのアプリケーションシナリオでソートを実装するために名前を数値に変換するソリューションでは、ユーザーはグループ、特に1つでソートする必要がある場合があります...

MapsTructを使用したシステムドッキングのフィールドマッピングの問題を簡素化する方法は? MapsTructを使用したシステムドッキングのフィールドマッピングの問題を簡素化する方法は? Apr 19, 2025 pm 06:21 PM

システムドッキングでのフィールドマッピング処理は、システムドッキングを実行する際に難しい問題に遭遇することがよくあります。システムのインターフェイスフィールドを効果的にマッピングする方法A ...

Intellijのアイデアは、ログを出力せずにSpring Bootプロジェクトのポート番号をどのように識別しますか? Intellijのアイデアは、ログを出力せずにSpring Bootプロジェクトのポート番号をどのように識別しますか? Apr 19, 2025 pm 11:45 PM

intellijideaultimatiateバージョンを使用してスプリングを開始します...

エンティティクラス変数名をエレガントに取得して、データベースクエリ条件を構築する方法は? エンティティクラス変数名をエレガントに取得して、データベースクエリ条件を構築する方法は? Apr 19, 2025 pm 11:42 PM

データベース操作にMyBatis-Plusまたはその他のORMフレームワークを使用する場合、エンティティクラスの属性名に基づいてクエリ条件を構築する必要があることがよくあります。あなたが毎回手動で...

Javaオブジェクトを配列に安全に変換する方法は? Javaオブジェクトを配列に安全に変換する方法は? Apr 19, 2025 pm 11:33 PM

Javaオブジェクトと配列の変換:リスクの詳細な議論と鋳造タイプ変換の正しい方法多くのJava初心者は、オブジェクトのアレイへの変換に遭遇します...

Redisキャッシュソリューションを使用して、製品ランキングリストの要件を効率的に実現する方法は? Redisキャッシュソリューションを使用して、製品ランキングリストの要件を効率的に実現する方法は? Apr 19, 2025 pm 11:36 PM

Redisキャッシュソリューションは、製品ランキングリストの要件をどのように実現しますか?開発プロセス中に、多くの場合、ランキングの要件に対処する必要があります。

eコマースプラットフォームSKUおよびSPUデータベースデザイン:ユーザー定義の属性と原因のない製品の両方を考慮する方法は? eコマースプラットフォームSKUおよびSPUデータベースデザイン:ユーザー定義の属性と原因のない製品の両方を考慮する方法は? Apr 19, 2025 pm 11:27 PM

eコマースプラットフォーム上のSKUおよびSPUテーブルの設計の詳細な説明この記事では、eコマースプラットフォームでのSKUとSPUのデータベース設計の問題、特にユーザー定義の販売を扱う方法について説明します。

See all articles