Hibernate Session get()vs load()实例差异
时间:2020-02-23 14:41:26 来源:igfitidea点击:
Hibernate Session提供了从数据库中获取数据的不同方法。
其中两个是– get()和load()。
这些方法还有很多重载方法,我们可以在不同情况下使用。
乍看之下,get()
和load()
看起来很相似,因为它们都是从数据库中获取数据,但是它们之间几乎没有什么区别,让我们以一个简单的例子来看一下。
package com.theitroad.hibernate.main; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import com.theitroad.hibernate.model.Employee; import com.theitroad.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= hyman, Salary= 100.0, {Address= AddressLine1= Albany Dr, City=San Jose, Zipcode=95129}
从输出中很明显,get()通过从数据库或者Hibernate 缓存中获取对象来返回对象,而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.theitroad.hibernate.model.Employee#100] at org.hibernate.internal.SessionFactoryImpl.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.theitroad.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.theitroad.hibernate.main.HibernateExample.main(HibernateExample.java:36)
仔细观察输出,当我们使用get()检索不存在的数据时,它返回null。
这是有道理的,因为它会尝试在数据被调用后立即加载。
使用load(),我们可以打印id,但是当我们尝试访问其他字段时,它会触发数据库查询,如果没有找到具有给定标识符的记录,则会引发org.hibernate.ObjectNotFoundException。
它是Hibernate 专用的运行时异常,因此我们无需显式捕获它。
我们也来看看一些重载的方法。
上面的get()和load()方法也可以如下编写。
Employee emp = (Employee) session.get("com.theitroad.hibernate.model.Employee", new Long(2)); Employee emp1 = (Employee) session.load("com.theitroad.hibernate.model.Employee", new Long(1)); Employee emp2 = new Employee(); session.load(emp1, new Long(1));
还有其他带有LockOptions参数的方法,但是我没有使用过。
注意,我们需要传递完整的类名作为参数。
根据以上说明,get()与load()之间存在以下区别:
get()会在调用后立即加载数据,而load()返回代理对象并仅在实际需要时才加载数据,因此load()更好,因为它支持延迟加载。
由于
load()
在找不到数据时会引发异常,因此仅当我们知道数据存在时才应使用它。当我们要确保数据库中存在数据时,应该使用
get()
。