Сеанс Hibernate предоставляет различные методы для извлечения данных из базы данных. Два из них – 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) {
//Подготовительная работа
SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
//Пример использования get()
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()
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");
//Закрытие ресурсов
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()
возвращает объект, извлеченный из базы данных или из кэша Hibernate, в то время как load()
возвращает только ссылку на объект, который на самом деле может не существовать; данные загружаются из базы данных или кэша только при доступе к другим свойствам объекта. Теперь давайте попробуем извлечь данные, которых нет в базе данных.
//Пример использования get()
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()
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
, если запись с заданным идентификатором не найдена. Это специфическое для Hibernate исключение времени выполнения Runtime Exception, поэтому нам не нужно явно его перехватывать. Давайте также посмотрим на некоторые из перегруженных методов. Вышеупомянутые методы 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() vs load():
-
get()
загружает данные сразу после вызова, тогда какload()
возвращает объект-прокси и загружает данные только тогда, когда это действительно необходимо, поэтомуload()
лучше, потому что он поддерживает ленивую загрузку. - Поскольку
load()
выбрасывает исключение, когда данные не найдены, мы должны использовать его только тогда, когда мы знаем, что данные существуют. - Мы должны использовать
get()
, когда хотим убедиться, что данные существуют в базе данных.
Вот и все, что касается методов получения и загрузки Hibernate, я надеюсь, это прояснит некоторые сомнения и поможет вам решить, какой из них использовать в различных ситуациях.