例を示しながら、Hibernate Sessionのget()とload()の違い

ハイバネートセッションは、データベースからデータを取得するための異なるメソッドを提供します。そのうちの2つは、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()はオブジェクトをデータベースから取得するか、ハイバネートキャッシュから取得しますが、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()を使用すると、IDを印刷できますが、他のフィールドにアクセスしようとすると、データベースクエリが発行され、指定された識別子でレコードが見つからない場合はorg.hibernate.ObjectNotFoundExceptionがスローされます。これはHibernate固有のランタイム例外なので、明示的にキャッチする必要はありません。いくつかのオーバーロードされたメソッドも見てみましょう。上記の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()の間には以下の違いがあります:

  1. get()は呼び出されるとすぐにデータを読み込みますが、load()はプロキシオブジェクトを返し、データが実際に必要な時にのみ読み込むため、load()の方がより良いです。遅延読み込みをサポートしているためです。
  2. load()はデータが見つからない場合に例外をスローするため、データが存在することを知っている場合にのみ使用する必要があります。
  3. データがデータベースに存在することを確認したい場合は、get()を使用する必要があります。

これでHibernateのgetとloadメソッドに関するすべてです。いくつかの疑問を解消し、異なるシナリオでどちらを使用するかを決定するのに役立つことを願っています。

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