Hibernate 会话 get() 与 load() 的区别(附示例

Hibernate Session 提供了不同的方式从数据库中获取数据。其中两个是-** Get()** 和** Load()** 。对于这些,我们也有很多重载方法,可以在不同的情况下使用。乍一看,get()Load()看起来很相似,因为它们都是从数据库获取数据,但它们之间几乎没有什么区别,让我们用一个简单的例子来看看它们。

 1package com.journaldev.hibernate.main;
 2
 3import org.hibernate.Session;
 4import org.hibernate.SessionFactory;
 5import org.hibernate.Transaction;
 6
 7import com.journaldev.hibernate.model.Employee;
 8import com.journaldev.hibernate.util.HibernateUtil;
 9
10public class HibernateGetVsLoad {
11
12    public static void main(String[] args) {
13    	
14    	//Prep Work
15    	SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
16    	Session session = sessionFactory.openSession();
17    	Transaction tx = session.beginTransaction();
18    	
19    	//Get Example
20    	Employee emp = (Employee) session.get(Employee.class, new Long(2));
21    	System.out.println("Employee get called");
22    	System.out.println("Employee ID= "+emp.getId());
23    	System.out.println("Employee Get Details:: "+emp+"\n");
24    	
25    	//load Example
26    	Employee emp1 = (Employee) session.load(Employee.class, new Long(1));
27    	System.out.println("Employee load called");
28    	System.out.println("Employee ID= "+emp1.getId());
29    	System.out.println("Employee load Details:: "+emp1+"\n");
30    	
31    	//Close resources
32    	tx.commit();
33    	sessionFactory.close();
34    }
35}

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

1Hibernate: 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=?
2Employee get called
3Employee ID= 2
4Employee Get Details:: Id= 2, Name= David, Salary= 200.0, {Address= AddressLine1= Arques Ave, City=Santa Clara, Zipcode=95051}
5
6Employee load called
7Employee ID= 1
8Hibernate: 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=?
9Employee load Details:: Id= 1, Name= Pankaj, Salary= 100.0, {Address= AddressLine1= Albany Dr, City=San Jose, Zipcode=95129}

从输出中可以明显看出,Get()通过从数据库或从Hibernate cache获取对象来返回对象,而Load()只返回一个可能并不实际存在的对象的引用,它仅在您访问该对象的其他属性时才从数据库或缓存加载数据。现在,让我们尝试获取数据库中不存在的数据。

 1//Get Example
 2try{
 3Employee emp = (Employee) session.get(Employee.class, new Long(200));
 4System.out.println("Employee get called");
 5if(emp != null){
 6System.out.println("Employee GET ID= "+emp.getId());
 7System.out.println("Employee Get Details:: "+emp+"\n");
 8}
 9}catch(Exception e){
10    e.printStackTrace();
11}
12
13//load Example
14try{
15Employee emp1 = (Employee) session.load(Employee.class, new Long(100));
16System.out.println("Employee load called");
17System.out.println("Employee LOAD ID= "+emp1.getId());
18System.out.println("Employee load Details:: "+emp1+"\n");
19}catch(Exception e){
20    e.printStackTrace();
21}

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

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

仔细观察输出,当我们使用get()检索不存在的数据时,它返回NULL 。这是有意义的,因为它试图在被调用时立即加载数据。使用Load(),我们可以打印id,但只要我们尝试访问其他字段,它就会触发数据库查询,如果没有找到具有给定标识符的记录,则抛出org.hibernate.ObjectNotFoundException。它是Hibernate特有的Runtime Exception,所以我们不需要显式地捕获它。让我们也来看看一些重载方法。上面的** get()和Load()** 方法也可以编写如下。

1Employee emp = (Employee) session.get("com.journaldev.hibernate.model.Employee", new Long(2));
2
3Employee emp1 = (Employee) session.load("com.journaldev.hibernate.model.Employee", new Long(1));
4
5Employee emp2 = new Employee();
6session.load(emp1, new Long(1));

还有其他带有`LockOptions‘参数的方法,但我还没有使用过它们。请注意,我们需要将完整的类名作为参数传递。基于以上解释,我们在Get()和Load() 之间有以下区别:

1.Get()一被调用就加载数据,而Load()返回代理对象,只在实际需要时加载数据,所以Load()更好,因为它支持延迟加载。 2.由于Load()在找不到数据时会抛出异常,所以我们应该在知道有数据的情况下才使用它。 3.当我们想要确保数据库中有数据时,应该使用get()

这就是Hibernate的Get和Load方法,我希望它将消除一些疑虑,并帮助您决定在不同的场景中使用哪种方法。

Published At
Categories with 技术
Tagged with
comments powered by Disqus