Hibernate Session get() 与 load() 的区别及示例
Hibernate Session提供了不同的方法来从数据库获取数据。其中两种是 - 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) {
//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();
}
}
当我执行上述代码时,它会产生以下输出。
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}
从输出中可以清楚地看出,通过从数据库或Hibernate 缓存get()
中获取对象来返回对象,而仅返回可能实际上不存在的对象的引用,只有当您访问对象的其他属性时,它才会从数据库或缓存中加载数据。现在让我们尝试获取数据库中不存在的数据。load()
//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();
}
上述代码产生以下输出。
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() 与 load()之间有以下区别:
get()
在调用时立即加载数据,而load()
返回代理对象并仅在实际需要时加载数据,因此load()
更好,因为它支持延迟加载。- 由于
load()
在找不到数据时会引发异常,因此我们应该只有当知道数据存在时才使用它。 get()
当我们想要确保数据存在于数据库中时,我们应该使用它。
这就是有关 Hibernate 获取和加载方法的全部内容,我希望它能够消除一些疑问并帮助您决定在不同场景中使用哪一种方法。