Hibernate Session get()vs load()实例差异

Hibernate Session provide different methods to fetch data from database. Two of them are – get() and load(). There are also a lot of overloaded methods for these, that we can use in different circumstances.

Hibernate Session提供了从数据库中获取数据的不同方法。 其中两个是– get()load() 。 这些方法还有很多重载方法,我们可以在不同的情况下使用。

At first look both get() and load() seems similar because both of them fetch the data from database, however there are few differences between them, let’s look at them with a simple example.

乍一看, 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();
	}
}

When I execute above code, it produces following output.

当我执行以上代码时,它将产生以下输出。

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}

From the output it’s clear that get() returns the object by fetching it from database or from hibernate cache whereas load() just returns the reference of an object that might not actually exists, it loads the data from database or cache only when you access other properties of the object.

从输出中很明显, get()通过从数据库或Hibernate缓存中获取对象来返回对象,而load()仅返回可能实际上不存在的对象的引用,仅当您访问时才从数据库或缓存中加载数据对象的其他属性。

Now let’s try to fetch data that doesn’t exists in the database.

现在,让我们尝试获取数据库中不存在的数据。

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

Above code produces following output.

上面的代码产生以下输出。

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)

Look at the output closely, when we use get() to retrieve data that doesn’t exists, it returns null. That makes sense because it try to load the data as soon as it’s called.

仔细观察输出,当我们使用get()检索不存在的数据时,它返回null 。 这是有道理的,因为它会在调用数据后立即尝试加载数据。

With load(), we are able to print the id but as soon as we try to access other fields, it fires database query and throws org.hibernate.ObjectNotFoundException if there is no record found with the given identifier. It’s hibernate specific Runtime Exception, so we don’t need to catch it explicitly.

使用load() ,我们可以打印id,但是,当我们尝试访问其他字段时,如果没有找到具有给定标识符的记录,它将触发数据库查询并引发org.hibernate.ObjectNotFoundException 。 它是Hibernate特定的Runtime Exception ,因此我们不需要显式捕获它。

Let’s look at some of the overloaded methods too. Above get() and load() methods could have been written as below too.

让我们也看看一些重载的方法。 上面的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));

There are other methods with LockOptions argument but I haven’t used them. Notice that we need to pass full class name as argument.

还有其他带有LockOptions参数的方法,但是我没有使用过。 注意,我们需要传递完整的类名作为参数。

Based on the above explanations we have following differences between get() vs load():

根据以上说明, get()与load()之间有以下区别:

  1. get() loads the data as soon as it’s called whereas load() returns a proxy object and loads data only when it’s actually required, so load() is better because it support lazy loading.

    get()会在调用后立即加载数据,而load()返回代理对象并仅在实际需要时才加载数据,因此load()更好,因为它支持延迟加载。
  2. Since load() throws exception when data is not found, we should use it only when we know data exists.

    由于未找到数据时load()会引发异常,因此仅当我们知道数据存在时才应使用它。
  3. We should use get() when we want to make sure data exists in the database.

    当我们要确保数据存在于数据库中时,应该使用get()

That’s all for hibernate get and load methods, I hope it will clear some doubts and help you in deciding which one to use in different scenarios.

Hibernate获取和加载方法就这些了,我希望它会清除一些疑问并帮助您确定在不同情况下使用哪种方法。

翻译自: https://www.journaldev.com/3472/hibernate-session-get-vs-load-difference-with-examples

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值