一次キャッシュは休止状態のクエリキャッシュとは異なりますか? 第 1 レベルおよびクエリ キャッシュについて言及している記事を見たことがありますが、混乱しています。
2 に答える
はい、別物です。Lee Chee Kiam が言うように、一次キャッシュはデフォルトで有効になっており、無効にすることはできません。基本的には、Hibernate がフェッチされたエンティティを最初に配置する場所であるため、同じオブジェクトの 2 番目のクエリは新しいオブジェクトをインスタンス化せず、ID による場合でもクエリを回避します。これについての例here。
//Open the hibernate session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
//fetch the department entity from database first time
DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());
//fetch the department entity again
department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());
session.getTransaction().commit();
HibernateUtil.shutdown();
Output:
Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource
Human Resource
First Level Cache は、IdentityMapパターンの Hibernate 実装であると言えます。
クエリ キャッシュはエンティティに厳密に関連しており、検索基準とその特定のクエリ フィルタを満たすエンティティとの間の関連付けを描画します (ここから)。クエリキャッシュは、クエリの生の結果のみを主キーとして保持します。休止状態で言えば、ID です。実際の水和オブジェクトは保持されません。
クエリ キャッシュはどのように機能しますか?
次の基準クエリがあるとします。
session.createCriteria(Person.class)
.add( Restrictions.eq("firstName", "Joey")
).setCacheable(true);
クエリ キャッシュは、キーがクエリ テキストとパラメーター値で構成され、値がクエリに一致するエンティティ ID のリストであるハッシュ マップのように概念的に見えます。
*----------------------------------------------------------*
| Query Cache |
|----------------------------------------------------------|
| ["from Person where firstName=?", ["Joey"] ] -> [1, 2] ] |
*----------------------------------------------------------*
そのため、次に同じ条件クエリを実行するときに、Hibernate はそのハッシュ マップを調べて、ID 1 と 2 を持つ Person が制限に一致することを解決します。この場合、クエリのコストを回避できます (この場合はほぼゼロですが、結合などを使用した高価なクエリになる可能性があります) が、Persons をクエリするためにデータベースにアクセスすることになります (今では ID によって何が非常に高速) Person オブジェクトを構築します。クエリ キャッシュは、Ehcache や infinispan などのサード パーティの実装を必要とするセカンド レベル キャッシュで頻繁に使用されます。
第 2 レベルのキャッシュにはエンティティ データが格納されますが、エンティティ自体は格納されません。データは、キーがエンティティ ID で、値がプリミティブ値のリストであるハッシュ マップのように見える「脱水」形式で格納されます。以下は、二次キャッシュの内容がどのように見えるかの例です。
*-----------------------------------------*
| Person Data Cache |
|-----------------------------------------|
| 1 -> [ "Joey" , "Q" , "Public" , null ] |
| 2 -> [ "Joey" , "D" , "Public" , 1 ] |
| 3 -> [ "Sara" , "N" , "Public" , 1 ] |
*-----------------------------------------*
そのため、クエリ キャッシュは ID 1 と 2 を提供し、Hibernate は ID 1 と 2 を持つ Person に対応する第 2 レベルのキャッシュ内の生データを使用してオブジェクトを構築します。
クエリ キャッシュと第 2 レベルのキャッシュは、読み取りが多く、更新がほとんどまたはまったくないエンティティ用です。あらゆるタイプのキャッシュにおける不整合の問題はよく知られているためです。そのため、Hibernate はキャッシュを無効にするか更新する必要があります (クラスター化されたキャッシュがある場合はレプリケーションが含まれます)。多くの更新を行うと、常にキャッシュが無効になり、益よりも害が大きくなります。
一次キャッシュはデフォルトで有効になっており、セッション単位です。クエリ キャッシュはデフォルトでは有効になっておらず、複数のセッションで共有されており、常に第 2 レベルのキャッシュと組み合わせて使用する必要があります。
クエリ キャッシュを有効にするには、次のプロパティを使用する必要があります。
hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=org.hibernate.cache.EhCacheProvider
hibernate.cache.use_query_cache=true