7

HQLクエリがどこから情報を取得するかを理解するのに苦労しています。私のプロジェクトは異なるスレッドを使用しており、各スレッドはデータベースに対して読み取り/書き込みを行います。スレッドは Session オブジェクトを共有しません。代わりに、HibernateUtilセッションを作成するクラスを使用しています。

最近まで、セッションを閉じたのは書き込み後だけで、読み取り後ではありませんでした。オブジェクトへの変更はすぐにデータベースに表示されます、他のスレッド (書き込みに使用されたものとは異なるセッション オブジェクト) で読み取ると、古い情報が取得されます。読み取りと書き込みは常に異なるスレッドで行われます。つまり、異なる Session オブジェクトと異なるセッション キャッシュを意味します。

HQLの代わりにを使用することで、セッション キャッシュではなく、常にデータベース (または第 2 レベルのキャッシュ) をターゲットにしているといつも思っていましたCriteriaが、コードをデバッグしているときに、HQL がセッション キャッシュ内のオブジェクトを探していることが明らかになりました。古い時代遅れのオブジェクトを取得しました。

HQL常にデータベースをターゲットにしていると仮定したのは間違っていましたか? または、少なくとも第 2 レベルのキャッシュですか?

PS: 私は 1 つのSessionFactoryオブジェクトのみを使用しています。

4

1 に答える 1

7

Hibernate には、キャッシングの異なる概念 (エンティティ キャッシュとクエリ キャッシュ) があります。エンティティ キャッシングは、セッション キャッシュ (および有効な場合は第 2 レベルのキャッシュ) が行うことです。

クエリのキャッシュが有効になっていない (デフォルトでは有効になっていない) と仮定すると、HQL はデータベースに対して実行されます。これにより、クエリに一致するエンティティの ID が返されます。これらのエンティティがすでにセッション キャッシュにある場合、Hibernate はデータベースからエンティティを再構築するのではなく、それらを返します。セッションにそれらの古いコピーがある場合 (別のセッションがデータベースを更新したため)、それが問題です。

主にその理由から、長時間のセッションを使用しないことをお勧めします。セッションの存続期間を、実行しようとしている特定の作業単位に制限してから、セッションを閉じる必要があります。これを行うことによるパフォーマンスの低下はほとんどまたはまったくありません (データベース接続プールを使用すると仮定します)。または、古いエンティティを取得しないようにするために を呼び出すこともできますがSession.clear()、予期しないパフォーマンスの副作用が発生する可能性があります。

于 2012-05-10T11:34:08.767 に答える