Diferencia entre Hibernate Session get() y load() con ejemplos

Sesión de Hibernate proporciona diferentes métodos para obtener datos de la base de datos. Dos de ellos son – get() y load(). También hay muchos métodos sobrecargados para estos, que podemos usar en diferentes circunstancias. A primera vista, tanto get() como load() parecen similares porque ambos obtienen los datos de la base de datos, sin embargo, hay algunas diferencias entre ellos, veámoslas con un ejemplo simple.

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) {
		
		//Trabajo de preparación
		SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
		Session session = sessionFactory.openSession();
		Transaction tx = session.beginTransaction();
		
		//Ejemplo de 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");
		
		//Ejemplo de 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");
		
		//Cerrar recursos
		tx.commit();
		sessionFactory.close();
	}
}

Cuando ejecuto el código anterior, produce la siguiente salida.

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}

Desde la salida, es claro que get() devuelve el objeto obteniéndolo de la base de datos o de la cache de Hibernate, mientras que load() simplemente devuelve la referencia de un objeto que podría no existir realmente, carga los datos de la base de datos o de la caché solo cuando accede a otras propiedades del objeto. Ahora intentemos obtener datos que no existen en la base de datos.

//Ejemplo de 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();
}

//Ejemplo de 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();
}

El código anterior produce la siguiente salida.

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)

Mira de cerca la salida, cuando usamos get() para recuperar datos que no existen, devuelve null. Eso tiene sentido porque intenta cargar los datos tan pronto como se llama. Con load(), podemos imprimir el identificador, pero tan pronto como intentamos acceder a otros campos, dispara una consulta a la base de datos y lanza org.hibernate.ObjectNotFoundException si no se encuentra ningún registro con el identificador dado. Es una Excepción en Tiempo de Ejecución específica de Hibernate, por lo que no necesitamos capturarlo explícitamente. Veamos también algunos de los métodos sobrecargados. Los métodos get() y load() podrían haber sido escritos de la siguiente manera.

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

Hay otros métodos con el argumento LockOptions, pero no los he usado. Observa que necesitamos pasar el nombre completo de la clase como argumento. Basándonos en las explicaciones anteriores, tenemos las siguientes diferencias entre get() vs load():

  1. get() carga los datos tan pronto como se llama, mientras que load() devuelve un objeto proxy y carga los datos solo cuando realmente es necesario, por lo que load() es mejor porque admite la carga perezosa.
  2. Dado que load() lanza una excepción cuando no se encuentra el dato, deberíamos usarlo solo cuando sepamos que el dato existe.
  3. Deberíamos usar get() cuando queramos asegurarnos de que el dato exista en la base de datos.

Eso es todo sobre los métodos get y load de Hibernate, espero que aclare algunas dudas y te ayude a decidir cuál usar en diferentes escenarios.

Source:
https://www.digitalocean.com/community/tutorials/hibernate-session-get-vs-load-difference-with-examples