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

Hibernate Session get() vs load() разница с примерами


Hibernate Session предоставляет различные методы для извлечения данных из базы данных. Два из них — get() и load(). Для них также существует множество перегруженных методов, которые мы можем использовать в разных обстоятельствах. На первый взгляд оба get() и load() кажутся похожими, потому что оба они извлекают данные из базы данных, однако между ними мало различий, давайте посмотрим на них с помощью простой пример.

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 HibernateGetVsLoad {

	public static void main(String[] args) {
		
		//Prep Work
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		Session session = sessionFactory.openSession();
		Transaction tx = session.beginTransaction();
		
		//Get Example
		Employee emp = (Employee) session.get(Employee.class, new Long(2));
		System.out.println("Employee get called");
		System.out.println("Employee ID= "+emp.getId());
		System.out.println("Employee Get Details:: "+emp+"\n");
		
		//load Example
		Employee emp1 = (Employee) session.load(Employee.class, new Long(1));
		System.out.println("Employee load called");
		System.out.println("Employee ID= "+emp1.getId());
		System.out.println("Employee load Details:: "+emp1+"\n");
		
		//Close resources
		tx.commit();
		sessionFactory.close();
	}
}

Когда я выполняю приведенный выше код, он выводит следующий вывод.

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=?
Employee get called
Employee ID= 2
Employee Get Details:: Id= 2, Name= David, Salary= 200.0, {Address= AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051}

Employee load called
Employee ID= 1
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=?
Employee load Details:: Id= 1, Name= Pankaj, Salary= 100.0, {Address= AddressLine1= Albany Dr, City=San Jose, Zipcode=95129}

Из вывода видно, что get() возвращает объект, извлекая его из базы данных или из кэша гибернации, тогда как load() просто возвращает ссылку на объект, который на самом деле может не существует, он загружает данные из базы данных или кэша только при доступе к другим свойствам объекта. Теперь давайте попробуем получить данные, которых нет в базе данных.

//Get Example
try{
Employee emp = (Employee) session.get(Employee.class, new Long(200));
System.out.println("Employee get called");
if(emp != null){
System.out.println("Employee GET ID= "+emp.getId());
System.out.println("Employee Get Details:: "+emp+"\n");
}
}catch(Exception e){
	e.printStackTrace();
}

//load Example
try{
Employee emp1 = (Employee) session.load(Employee.class, new Long(100));
System.out.println("Employee load called");
System.out.println("Employee LOAD ID= "+emp1.getId());
System.out.println("Employee load Details:: "+emp1+"\n");
}catch(Exception e){
	e.printStackTrace();
}

Приведенный выше код выводит следующий вывод.

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=?
Employee get called
Employee load called
Employee LOAD ID= 100
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=?
org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.journaldev.hibernate.model.Employee#100]
	at org.hibernate.internal.SessionFactoryImpl$1$1.handleEntityNotFound(SessionFactoryImpl.java:253)
	at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:262)
	at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:176)
	at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286)
	at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
	at com.journaldev.hibernate.model.Employee_$$_jvst407_1.toString(Employee_$$_jvst407_1.java)
	at java.lang.String.valueOf(String.java:2847)
	at java.lang.StringBuilder.append(StringBuilder.java:128)
	at com.journaldev.hibernate.main.HibernateExample.main(HibernateExample.java:36)

Внимательно посмотрите на вывод: когда мы используем get() для извлечения данных, которых не существует, он возвращает null. Это имеет смысл, потому что он пытается загрузить данные, как только вызывается. С помощью load() мы можем распечатать идентификатор, но как только мы попытаемся получить доступ к другим полям, он запускает запрос к базе данных и выдает org.hibernate.ObjectNotFoundException, если есть не найдена запись с данным идентификатором. Это исключение времени выполнения для гибернации, поэтому нам не нужно его явно перехватывать. Давайте также рассмотрим некоторые из перегруженных методов. Приведенные выше методы get() и load() также могли быть написаны так, как показано ниже.

Employee emp = (Employee) session.get("com.journaldev.hibernate.model.Employee", new Long(2));

Employee emp1 = (Employee) session.load("com.journaldev.hibernate.model.Employee", new Long(1));

Employee emp2 = new Employee();
session.load(emp1, new Long(1));

Есть и другие методы с аргументом LockOptions, но я их не использовал. Обратите внимание, что нам нужно передать полное имя класса в качестве аргумента. Основываясь на приведенных выше объяснениях, у нас есть следующие различия между get() и load():

  1. get() загружает данные сразу после вызова, тогда как load() возвращает прокси-объект и загружает данные только тогда, когда это действительно необходимо, поэтому load() лучше, потому что поддерживает отложенную загрузку.
  2. Поскольку load() генерирует исключение, когда данные не найдены, мы должны использовать его только тогда, когда знаем, что данные существуют.
  3. Мы должны использовать get(), когда хотим убедиться, что данные существуют в базе данных.

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