Защо имате нужда от кеш на заявки

Нека пренапишем нашия пример с намирането на служители в 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();

Кешът на заявките е подобен на кеш от второ ниво. Но за разлика от него, тук ключът към данните в кеша не е идентификаторът на обекта, а наборът от параметри на заявката. А самите данни са идентификаторите на обектите, които отговарят на критериите на заявката. Следователно е рационално този кеш да се използва с кеш от второ ниво.

Изчистване на кеша

Една от важните задачи при работа с кеш е да се уверите, че кешираните обекти се променят и да ги премахнете от кеша (or да ги актуализирате). Hibernate прави това много добре. Понякога дори изглежда, че той се ръководи от правилото „изчистете кеша във всяка неразбираема ситуация“.

Да приемем, че искате да актуализирате потребителските данни чрез HQL:

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

Hibernate не може да знае точно Howво се е променило в базата данни, но знае, че променяте обект Employee. Следователно, след изпълнение на тази заявка, Hibernate ще изтрие всички обекти от тип Employee от своя кеш.

Но NativeQuery работи още по-интересно:

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

Беше изпълнена собствена SQL заявка към базата данни. Това означава, че нещо се е променило в базата данни - заявката е извикана в метода executeUpdate() . Следователно в този случай Hibernate ще играе на сигурно и ще премахне всички обекти от всички видове от своя кеш .

How ти харесва това Извиквате безвредна заявка и Hibernate в отговор изтрива всички данни от кеша! Това със сигурност е по-добре, отколкото ако запази предмети, които се различават от основата, но това е!

Затова създателите на Hibernate бързо измислиха How да помогнат на Hibernate в този случай. Можете да му кажете кой тип обект да премахне от кеша:

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
Забележка . Собствените заявки за избор не изчистват кеша , а само вмъкване, актуализиране, изтриване, извикване на proceduresи и т.н.

Ръчно изчистване на кеша

Поради определени причини може да искате сами да изтриете обект от кеша. Това може да стане по различни начини.

Забележка . Обектите в кеша се съхраняват в групи, наречени региони . По подразбиране името на региона е същото като името на класа. Следователно, ако имате обекти от тип com.codegym.Employee , тогава всички те ще бъдат съхранени в група (регион) с името “ com.codegym.employee ”.

Ако искате да получите достъп до кеша и да направите нещо с него, можете да го направите с обекта SessionFactory и метода getCache() :

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

Ако искате да изтриете данни от всички групи (региони), тогава трябва да изпълните следната заявка:

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

За да премахнете един обект от кеша, трябва да предадете неговото име (тип) и идентификатор. Можете да направите това по два начина:

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);