JPAステッピングの問題
最近、プロジェクトでJPAが使用されました。JPAを使用する場合、過失による問題、またはJPAの不慣れによる問題が発生しました。問題は次のとおりです。
問題の原因を要約します
。方法Aでは、データベースの注文テーブル(注文)の日付フィールドが更新されますが、トランザクションが送信されていない場合は、mqメッセージが受信され、ステータスフィールドのステータスは注文テーブルは更新されますが、Aメソッドはまだトランザクションをコミットしていないため、ステータスフィールドを更新するmqメソッドは、Aメソッドの日付更新情報を上書きし、Aメソッドが更新される前の値で日付を上書きします。 。
ここでは、タイミング図の意味を説明します。
- システムAは私が担当するシステムであり、システムBは私のダウンストリームです。顧客の予約時間の後、最初にデータベースの注文テーブルに顧客の予約時間を保存します。これはシーケンス図の最初のステップです。
- ステップ2:今回はダウンストリームに同期されます、これは簡単なダボインターフェース呼び出しです
- 3番目のステップでは、ここで他のロジックを引き続き扱いますが、問題があります。3つのステップ1、2、および3が同じトランザクション内にある場合です。この場合、1、2、および3がすべて完了しました。トランザクションをコミットし、データベースの注文テーブルの時刻を更新します
- ただし、ステップ2では、ダウンストリームインターフェイスを呼び出した後、ダウンストリームがmqメッセージを返送して、Aシステムにステータス変更(updateStatusメソッド)を通知します。ここでのステータスは、自分の注文のステータスではありません。ダウンストリームのビジネスステータス(Xフィールド)だけでなく、注文テーブルにもあるため、手順4でメッセージを受信した後、注文IDに従って注文テーブルをクエリします。
- 5番目のステップは、Xフィールドの値を更新することです。問題はここにあります。5番目のステップでは、図の便宜上、JPAと呼びました。
org.springframework.data.repository.CrudRepository#save
この保存方法は、レコードが存在しない場合は挿入し、レコードが存在する場合は更新を実行します。
では、どこに問題があるのでしょうか。
- updateDateメソッドトランザクションがまだコミットされていない場合、ダウンストリームmqメッセージが受信されます
- メッセージを受信したら、主キーIDに従ってデータベースにクエリを実行し、注文レコードを取得します。この時点では、updateDateトランザクションがまだ送信されていないため、注文レコードの時間フィールドはnullのままです。
- 次に、ステップ5でロジック処理が実行されると、updateDateはトランザクションをコミットしますが、トランザクションが送信される前に、updateStatusメソッドはすでにデータベースにクエリを実行しており、取得された日付はnullであるため、updateStatusがステータスを更新する場合は、日付を直接入力します。フィールドをnullに更新
したがって、問題は次のとおり
です。1。メソッドAのトランザクションが送信されていない場合、メソッドBはデータベースからデータを照会しましたが、2。
メソッドBは、Aのトランザクションが送信される前にすべてのフィールドを更新するために使用されました。トランザクションはBで送信されました。以前は、トランザクションAが送信されました
。3。メソッドBが更新されると、トランザクションAの更新されたフィールドが上書きされます。
解決
当時、オンラインでの公開に熱心だったため、updateStatusで呼び出されたjpaのsaveメソッドを一時的にローカルSQLに置き換えて書き込みました。
@Query(value = "update order set status = :status where id = :id",nativeQuery = true)
@Modifying
ローカルSQLを使用して、このメソッドで更新する必要があるフィールドのみを更新します
2番目の方法:
後で検討しました。updateDateメソッドでトランザクションの範囲を縮小することを検討できます。1と2が実行された後、トランザクションが送信されます。3番目のステップの他のロジックについては、エラーが発生した場合、3番目のステップのみをロールバックします。顧客が再度予約を行うと、最後の予約が失敗した時刻が上書きされ
、大規模なトランザクション方法を使用する場合でも一定のリスクがあります。
総括する
要約すると、それは一文です:なじみのない技術については、注意してください。フレームワークの特性を理解していない場合は、メソッドの実行を自分で制御してみてください。これにより、少なくともシステムの安定性を確保できます。 。ビジネスロジックとコードをリファクタリングする