1

hibernate-entitymanager で Hibernate 2.6 を使用しています。オブジェクトで 2 つのトランザクションが競合する状況をキャッチして処理しようとしています。何が起こるかは次のとおりです。

2 つのスレッドが @Version フィールドを持つ単一のオブジェクトを更新しています。コミット競合を失ったスレッドは、フラッシュ時に StaleObjectStateException をログに記録します。例外はスローされず、ログに記録されるだけです。その時点で、トランザクションはロールバックのみとマークされていると思います。

その後、スレッドがコミットを実行しようとすると、RollbackException で失敗します。トランザクションがロールバックされる理由をコードで見つける方法が見つかりませんでした。

コードでそのような状況をキャッチして処理する方法はありますか? 基本的には StaleObjectStateException をキャッチしたいのですが、問題はスローされないことです。

更新:鳥瞰図から達成しようとしているのは次のとおりです。

JBoss で J2EE アプリケーションを実行しています。内部タイマーによって呼び出されるサービスと、UI から呼び出されるサービスがいくつかあります。また、重要なエンティティが 1 つあります。データの不整合が発生する可能性があるため、異なるスレッドがそのエンティティ クラスのオブジェクトを同時に更新できないようにする必要があります。これが、私が楽観的ロックを実装している理由です。

楽観的ロックの問題が発生した場合、私はこの状況を一般的に処理しようとしています。私はそれを非常に高いレベルでキャッチし、有効なユーザー メッセージを表示したいと考えています (私の場合、最高レベルは RestEasy の ExceptionMapper です)。問題は、RollbackException をキャッチした時点ですでに手遅れであることです。

手動でフラッシュしません。ほとんどの EJB は CMT を使用しており、セッションは自動的にフラッシュされます。

4

2 に答える 2

2

アルテム、

あなたが達成しようとしていることを簡単に説明できますか?鳥瞰図、明らかに-これは(呼び出された)UIコードですか?それともサーバー側のプロセスですか(スレッドを直接制御できますか)?私が尋ねる理由は、これとあなたの他の関連する質問から、設計されていないものに楽観的ロックを使用しようとしていて、それがすべての問題を引き起こしているという(おそらく間違った)感じがするからです。

行く限り、明示的/暗黙的なフラッシュを処理する両方からStaleObjectStateException最も確実にスローされます。手動で flush() を呼び出していますか? そうでない場合、おそらく例外は、自動フラッシュの周りのラッパー コードによってキャッチ/ログに記録されています (Spring? TransactionManager? EntityManager?)DefaultFlushEventListenerAutoFlushEventListener

アップデート

質問を明確にしていただきありがとうございます。複数のスレッドが同じエンティティ同時に変更するのを防ぐか、複数のユーザーが同時に編集しようとするのを防ぐかについては、まだ少し不明です。

前者のシナリオは、楽観的ロックによって処理できます。ただし、明示的に指定flush()しないと、非決定論的になります (最初に変更を行ったスレッドは最初にフラッシュ/コミットされない可能性があります)。詳細については、この質問に対する私の回答を参照してください。自動フラッシュのもう 1 つの問題は、現在発生している問題です。失敗したバージョン チェックはフラッシュするまで検出されず、そのフラッシュがトランザクションのコミット試行と一致する場合、スローされる例外は RollbackException です。いずれにせよ、トランザクション全体がロールバックされます。

後者のシナリオ (ユーザーが編集できないようにする) は、楽観的ロックでは処理できません。代わりに、データベースまたはアプリケーション レベルでペシミスティック ロックを実装する必要があります。つまり、プロセスは次のとおりです。

  1. ユーザーがエンティティを編集したい
  2. エンティティにロックが存在するかどうかを確認します
  3. YES - 編集を禁止します (読み取り専用表示を許可しますか?)
  4. いいえ - エンティティをロックし、編集を許可します
  5. 変更をコミット (キャンセル) します。ロック解除

この方法を使用する場合は、ユーザーが一定期間操作を行わないと、既存のロックを必ず期限切れにしてください。


この場合、同時に1を変更することは実際には正確ではありません (それがトランザクションの目的です)。古いバージョンに基づいて、あるスレッドが別のスレッドの編集を上書きするのを防ぐことについて話しているのです。

于 2009-09-21T18:16:03.163 に答える
0

NHProfを見てください。Nhibernate プロファイリングに関連するあらゆる種類のことを支援できます。

于 2009-09-21T11:48:46.227 に答える