クエリキャッシュが必要な理由

HQL で従業員を取得する例を書き直してみましょう。

Employee director1 = session.createQuery("from Employee where id = 4").uniqueResult();
Employee director2 = session.createQuery("from Employee where id = 4").uniqueResult();

assertTrue(director1 != director2);

このようなクエリの結果は、一次キャッシュにも二次キャッシュにも保存されません。

これはまさにクエリ キャッシュが使用できる場所です。これもデフォルトでは無効になっています。これを有効にするには、構成ファイルに次の行を追加します。

<property name="hibernate.cache.use_query_cache" value="true"/>

しかし、これは解決策の半分にすぎません。クエリ キャッシュを有効にしましたが、どのクエリ結果をキャッシュするかを指定する必要もあります。これはクエリに記述する必要があります。

Query query = session.createQuery("from Employee where id = 4");
query.setCacheable(true);
Employee director1 = query.uniqueResult();

クエリ キャッシュは 2 次キャッシュに似ています。ただし、それとは異なり、ここではキャッシュ データのキーはオブジェクト識別子ではなく、クエリ パラメーターのセットです。データ自体は、クエリ基準に一致するオブジェクトの識別子です。したがって、このキャッシュを 2 次キャッシュと併用するのが合理的です。

キャッシュをクリアする

キャッシュを操作するときの重要なタスクの 1 つは、キャッシュされたオブジェクトが変更されていることを確認し、キャッシュから削除 (または更新) することです。Hibernate はこれを非常にうまく実行します。時々、彼は「理解できない状況ではキャッシュをクリアする」というルールに従っているようにさえ見えます。

HQL 経由でユーザー データを更新するとします。

Query query = session.createQuery("update Employee set name=’Alex’ where id = 4")
query. executeUpdate();

Hibernate はデータベース内で何が変更されたかを正確に知ることはできませんが、Employee オブジェクトが変更されていることは知っています。したがって、このクエリの実行後、Hibernate はタイプ Employee のすべてのオブジェクトをキャッシュから削除します。

しかし、NativeQuery はさらに興味深い動作をします。

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4")
nativeQuery.executeUpdate();

データベースに対するネイティブ SQL クエリが実行されました。これは、データベース内で何かが変更されたことを意味します。リクエストは、executeUpdate()メソッドで呼び出されました。したがって、この場合、Hibernate は安全策を講じて、すべてのタイプすべてのオブジェクトをキャッシュから削除します。

お気に召しましたか?無害なリクエストを呼び出すと、それに応じて Hibernate がキャッシュからすべてのデータを消去します。これは、ベースとは異なるオブジェクトを保持するよりも確かに優れていますが、それだけです。

したがって、Hibernate の作成者は、この場合に Hibernate を支援する方法をすぐに考え出しました。どのエンティティ タイプをキャッシュから削除するかを指定できます。

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
備考. ネイティブ選択クエリはキャッシュをフラッシュせず、挿入、更新、削除、プロシージャ呼び出しなどのみを行います。

手動キャッシュクリア

特定の理由により、キャッシュからオブジェクトを自分で削除したい場合があります。これはさまざまな方法で実行できます。

注意してください。キャッシュ内のオブジェクトは、リージョンと呼ばれるグループに格納されます。デフォルトでは、領域名はクラス名と同じです。したがって、タイプcom.codegym.Employeeのオブジェクトがある場合、それらはすべて「 com.codegym.employee 」という名前のグループ (領域) に保存されます。

キャッシュにアクセスして何かを実行したい場合は、SessionFactory オブジェクトと getCache ()メソッドを使用して実行できます。

session.getSessionFactory().getCache().evictQueryRegion("com.codegym.employee”);

すべてのグループ (リージョン) からデータを削除する場合は、次のクエリを実行する必要があります。

session.getSessionFactory().getCache().evictAllRegions();

キャッシュから 1 つのオブジェクトを削除するには、その名前 (タイプ) と ID を渡す必要があります。これは 2 つの方法で行うことができます。

session.getSessionFactory().getCache().evictEntityData("Employee, 4);

session.getSessionFactory().getCache().evictEntityData(com.codegym.Employee.class, 4);

特定のオブジェクトがキャッシュ内にあるかどうかを確認することもできます。

session.getSessionFactory().getCache().containsEntity("Employee, 4);
session.getSessionFactory().getCache().containsEntity(com.codegym.Employee.class, 4);