1

長時間実行される会話 (JPA/Hibernate および Seam 2.2 を使用) での第 1 レベルのキャッシュに問題があります。

長時間実行される会話を使用する検索ページがあります (いくつかの ajax インタラクション、モーダルでの編集などに必要です)。

問題は、別のユーザーがエンティティを変更したときに、ユーザーが検索ボタンを再度クリックしたときに変更が表示されないことです。ここで同様の問題を参照してください

そのため、長時間実行されている会話エンティティは第 1 レベルのキャッシュから読み込まれますが、各エンティティで手動で更新を呼び出さない限り、他のトランザクションで行われた変更は読み込まれません。

CacheMode.IGNORE または CacheMode.REFRESH (hibernate クエリ経由) を使用しようとしましたが、2 番目のレベルのキャッシュのみを処理するため、問題は解決しません。

選択クエリがデータベースに送信されていることがわかりますが、Hibernate はまだ第 1 レベルのキャッシュにキャッシュされたオブジェクトを使用しているようです。

新しい検索を行う前に以前の検索からエンティティを削除しようとしましたが、それはうまくいきましたが、後で削除されたエンティティを指しているオブジェクトがまだセッションにあったため、有線の問題に遭遇していました。追加する必要があります

@org.hibernate.annotations.Cascade({org.hibernate.annotations.CascadeType.EVICT,org.hibernate.annotations.CascadeType.REFRESH})

エンティティの関係についてですが、見逃すのは簡単です。

ホール セッションをクリアすることもできますが、それによって LazyInitializationErrors が発生する可能性があります。

クエリで第 1 レベルのキャッシュを使用しないように JPA/Hibernate に指示する方法はありませんか?

編集:なぜうまくいかないのかという良い答えがありますが、各エンティティを更新するという提案は理想的ではありません。以前にこれを使用したことがありますが、問題は、たとえば 200 エントリのリストの場合、データベースに対して 200 の個別のロードが生成され、非常に遅くなることです。これら 200 のエントリのうち、変更された可能性があるのは 1 つまたは 2 つだけです。では、どのエンティティが変更されたかをどのように識別しますか! 変更ごとに更新されるエンティティにタイムスタンプを使用すると、それを使用できると思います。前回の検索のタイムスタンプを記録し、その後変更されたリスト内のエンティティを検索します。もっとエレガントなソリューションはありますか?

4

1 に答える 1

3

これを回避するには、EVENT スコープで別の永続化コンテキスト ファクトリを定義し、それをクエリに使用します。でcomponents.xml:

<persistence:managed-persistence-context scope="event" auto-create="true" 
    entity-manager-factory="#{yourfactory}" name="eventScopedEM" />

これにより、会話全体で同じエンティティ マネージャーを保持するのではなく、すべてのページ イベントで新しいエンティティ マネージャーが作成されます。#{entityManager}他のすべての用途のために、他の会話スコープの永続化コンテキスト ファクトリ (既定では ) を保持します。コンポーネントを使用してクエリを実行する場合はEntityQuery、エンティティ マネージャーの名前を設定することを忘れないでください (それ以外の場合は既定でentityManager)、getPersistenceContextName()メソッドをオーバーライドする (Java ベースのクエリ コンポーネントの場合) か、エンティティ マネージャーを明示的に設定する (xml ベースのクエリ コンポーネントの場合)。次に例を示します。

<framework:entity-query entityManager="#{eventScopedEM}">
    <framework:ejbql>from MyEntity</framework:ejbql>
    ...
</framework:entity-query>
于 2013-04-03T13:42:18.267 に答える