1

HibernateでJBossを実行していて、この問題が発生しています。

セッションBeanがEntityManagerを使用してエンティティを検索する場合、そのエンティティはEntityManagerのキャッシュにすでに存在している可能性があり、その状態はすでに古くなっている可能性があります。コードがそのようなエンティティを使用して決定を下す場合、バグを引き起こす可能性のある誤った決定を行う可能性があります。

これが例です。

HTTPリクエスト1.セッションBeanはエンティティインスタンスを作成し、フィールド「A」を値1に設定して保存します。永続化されたエンティティはID=4を取得します。

HTTPリクエスト2。セッションBeanはID=4のエンティティを検索し、そのフィールド「A」を値2に設定して保存します。

HTTPリクエスト3.セッションBeanは、ID = 4のエンティティを検索し、そのフィールド「A」をチェックします。値が1の場合は1つのことを行い、2の場合は別のことを行います。

リクエスト3のEMがリクエスト1と同じである場合、望ましくない動作が発生します。私はこれをテストし、約を得ました。失敗の10%のケース。

だから問題は-これを回避する方法は?エンティティが最新であることを確認する必要があるたびにem.refresh()またはem.clear()を呼び出すことは、リソースの浪費のようです。

4

1 に答える 1

1

アルテム、

これはあなたの質問の中で繰り返される テーマのようです:-)

あなたが以前に与えた答え(私のものを含む)はあなたが望んでいたものではないかもしれないことを私は理解していますが、それらは変わることはありません:

  • エンティティマネージャーはHibernateセッションにマップされており、通常は短命である必要があります。これは、 Hibernateセッションに関連する作業単位、トランザクション、および範囲の適切な説明です。これまでに見たことがない場合は、見てください。
  • アプリケーションが常にエンティティマネージャーを保持している場合は、その戦略の変更を真剣に検討する必要があります。メソッドを使用するよりも本当に長いトランザクションが必要ないくつかの場所でそれを実行している場合はrefresh()、すべての悪の中で間違いなく少ないです。
  • 実装がクラスター化された第2レベルのキャッシュとは異なり、セッションレベルのキャッシュは設計上異なるセッション(エンティティマネージャー)間で同期されず、同じエンティティへの同時更新は、Hibernateによって提供される楽観的ロックまたはアプリケーションレベルのロックによって処理されます。
  • 理論的には(ORMアクセスが十分に分離されている場合)、さまざまなエンティティマネージャーが保持するエンティティの独自のキャッシュ(必要に応じてクラスター化可能)を維持できます。キャッシュの同期を維持するには、適切なイベントリスナーをそれぞれに登録する必要があります。ただし、このアプローチには強くアドバイスします。実装が複雑でバグが発生しやすいだけでなく、これでHibernateのパラダイムに反対することになります。
于 2009-08-17T15:22:59.743 に答える