Поиск по сайту:

Кэширование в спящем режиме — кэш первого уровня


Добро пожаловать в Hibernate Caching — учебник по примерам кэширования первого уровня. Недавно мы изучали HQL для запуска SQL-запросов объектно-ориентированным способом. Сегодня мы рассмотрим один из важных аспектов Hibernate — Hibernate Cache.

Спящее кэширование

  1. Кэш первого уровня. Кэш первого уровня гибернации связан с объектом Session. Кэш первого уровня спящего режима включен по умолчанию, и его невозможно отключить. Однако спящий режим предоставляет методы, с помощью которых мы можем удалить выбранные объекты из кеша или полностью очистить кеш. Любой объект, кэшированный в сеансе, не будет виден другим сеансам, а при закрытии сеанса все кэшированные объекты также будут потеряны.
  2. Кэш второго уровня. Кэш второго уровня гибернации по умолчанию отключен, но мы можем включить его в настройках. В настоящее время EHCache и Infinispan обеспечивают реализацию кэша второго уровня Hibernate, и мы можем их использовать. Мы рассмотрим это в следующем руководстве по кэшированию в спящем режиме.
  3. Кэш запроса: 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, которые могут быть получены из вышеуказанной программы:

  1. Кэш первого уровня в спящем режиме включен по умолчанию, для этого не требуется никаких настроек.
  2. Кэш первого уровня гибернации зависит от сеанса, поэтому, когда мы получаем одни и те же данные в одном и том же сеансе, запрос не запускается, тогда как в другом сеансе запускается запрос для загрузки данных.
  3. Кэш первого уровня гибернации может иметь старые значения, как вы можете видеть выше, я перевел свою программу в спящий режим на 10 секунд, и за это время я обновил значение (имя от Pankaj до PankajK) в базе данных, но это не получить отражение в том же сеансе. Но в другом сеансе мы получили обновленное значение.
  4. Мы можем использовать сеансовый метод evict() для удаления одного объекта из кэша первого уровня режима гибернации.
  5. Мы можем использовать сеансовый метод clear(), чтобы очистить кеш, т.е. удалить все объекты из кеша.
  6. Мы можем использовать сеансовый метод contains(), чтобы проверить, присутствует ли объект в кеше гибернации или нет, если объект найден в кеше, он возвращает true или возвращает false.< /li>
  7. Поскольку спящий режим кэширует все объекты в кэше первого уровня сеанса, при выполнении массовых запросов или пакетных обновлений необходимо очищать кеш через определенные промежутки времени, чтобы избежать проблем с памятью.

Это все, что касается кэширования спящего режима и примера кеша первого уровня, в будущих постах мы рассмотрим реализацию кэша второго уровня гибернации — EHCache.