Кэширование в спящем режиме — кэш первого уровня
Добро пожаловать в Hibernate Caching — учебник по примерам кэширования первого уровня. Недавно мы изучали HQL для запуска SQL-запросов объектно-ориентированным способом. Сегодня мы рассмотрим один из важных аспектов Hibernate — Hibernate Cache.
Спящее кэширование
- Кэш первого уровня. Кэш первого уровня гибернации связан с объектом Session. Кэш первого уровня спящего режима включен по умолчанию, и его невозможно отключить. Однако спящий режим предоставляет методы, с помощью которых мы можем удалить выбранные объекты из кеша или полностью очистить кеш. Любой объект, кэшированный в сеансе, не будет виден другим сеансам, а при закрытии сеанса все кэшированные объекты также будут потеряны.
- Кэш второго уровня. Кэш второго уровня гибернации по умолчанию отключен, но мы можем включить его в настройках. В настоящее время EHCache и Infinispan обеспечивают реализацию кэша второго уровня Hibernate, и мы можем их использовать. Мы рассмотрим это в следующем руководстве по кэшированию в спящем режиме.
- Кэш запроса: Hibernate также может кэшировать набор результатов запроса. Hibernate Query Cache не кэширует состояние реальных сущностей в кеше; он кэширует только значения идентификатора и результаты типа значения. Поэтому его всегда следует использовать вместе с кешем второго уровня.
Кэширование в спящем режиме — пример кэша первого уровня
Для моего примера программы кэширования первого уровня в спящем режиме я использую ту же конфигурацию, что и в примере HQL, вы можете проверить это, настроить таблицы и заполнить их фиктивными данными. Давайте сначала посмотрим на программу, ее вывод, а затем мы рассмотрим некоторые важные моменты, связанные с кэшем первого уровня Hibernate. HibernateCacheExample.java
package com.journaldev.hibernate.main;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.journaldev.hibernate.model.Employee;
import com.journaldev.hibernate.util.HibernateUtil;
public class HibernateCacheExample {
public static void main(String[] args) throws InterruptedException {
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.getCurrentSession();
Transaction tx = session.beginTransaction();
//Get employee with id=1
Employee emp = (Employee) session.load(Employee.class, new Long(1));
printData(emp,1);
//waiting for sometime to change the data in backend
Thread.sleep(10000);
//Fetch same data again, check logs that no query fired
Employee emp1 = (Employee) session.load(Employee.class, new Long(1));
printData(emp1,2);
//Create new session
Session newSession = sessionFactory.openSession();
//Get employee with id=1, notice the logs for query
Employee emp2 = (Employee) newSession.load(Employee.class, new Long(1));
printData(emp2,3);
//START: evict example to remove specific object from hibernate first level cache
//Get employee with id=2, first time hence query in logs
Employee emp3 = (Employee) session.load(Employee.class, new Long(2));
printData(emp3,4);
//evict the employee object with id=1
session.evict(emp);
System.out.println("Session Contains Employee with id=1?"+session.contains(emp));
//since object is removed from first level cache, you will see query in logs
Employee emp4 = (Employee) session.load(Employee.class, new Long(1));
printData(emp4,5);
//this object is still present, so you won't see query in logs
Employee emp5 = (Employee) session.load(Employee.class, new Long(2));
printData(emp5,6);
//END: evict example
//START: clear example to remove everything from first level cache
session.clear();
Employee emp6 = (Employee) session.load(Employee.class, new Long(1));
printData(emp6,7);
Employee emp7 = (Employee) session.load(Employee.class, new Long(2));
printData(emp7,8);
System.out.println("Session Contains Employee with id=2?"+session.contains(emp7));
tx.commit();
sessionFactory.close();
}
private static void printData(Employee emp, int count) {
System.out.println(count+":: Name="+emp.getName()+", Zipcode="+emp.getAddress().getZipcode());
}
}
Когда мы запускаем приведенный выше пример, выходные данные содержат много информации, связанной со спящим режимом. Но нас в основном интересуют выходные данные нашего кода и запросы, запускаемые спящим режимом для загрузки данных. Выходной фрагмент выглядит следующим образом.
Hibernate Configuration loaded
Hibernate serviceRegistry created
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
1:: Name=Pankaj, Zipcode=95129
2:: Name=Pankaj, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
3:: Name=PankajK, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
4:: Name=David, Zipcode=95051
Session Contains Employee with id=1?false
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
5:: Name=Pankaj, Zipcode=95129
6:: Name=David, Zipcode=95051
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
7:: Name=Pankaj, Zipcode=95129
Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
8:: Name=David, Zipcode=95051
Session Contains Employee with id=2?true
Кэш первого уровня в спящем режиме Важные моменты
Важные моменты о кеше первого уровня в Hibernate, которые могут быть получены из вышеуказанной программы:
- Кэш первого уровня в спящем режиме включен по умолчанию, для этого не требуется никаких настроек.
- Кэш первого уровня гибернации зависит от сеанса, поэтому, когда мы получаем одни и те же данные в одном и том же сеансе, запрос не запускается, тогда как в другом сеансе запускается запрос для загрузки данных.
- Кэш первого уровня гибернации может иметь старые значения, как вы можете видеть выше, я перевел свою программу в спящий режим на 10 секунд, и за это время я обновил значение (имя от Pankaj до PankajK) в базе данных, но это не получить отражение в том же сеансе. Но в другом сеансе мы получили обновленное значение.
- Мы можем использовать сеансовый метод
evict()
для удаления одного объекта из кэша первого уровня режима гибернации. - Мы можем использовать сеансовый метод
clear()
, чтобы очистить кеш, т.е. удалить все объекты из кеша. - Мы можем использовать сеансовый метод
contains()
, чтобы проверить, присутствует ли объект в кеше гибернации или нет, если объект найден в кеше, он возвращает true или возвращает false.< /li> - Поскольку спящий режим кэширует все объекты в кэше первого уровня сеанса, при выполнении массовых запросов или пакетных обновлений необходимо очищать кеш через определенные промежутки времени, чтобы избежать проблем с памятью.
Это все, что касается кэширования спящего режима и примера кеша первого уровня, в будущих постах мы рассмотрим реализацию кэша второго уровня гибернации — EHCache.