在Hibernate框架中,最常用到的加载方式就非Get和Load莫属了,然而Get和Load在加载方式上边还有很多的不同,下面让我们来分析一下他们的不同之处。
区别
从返回的结果上来看,get、load在检索到数据的时候,会返回对象(代理对象或实体对象),但他们的检索方式不同,这个后续在细说。get检索不到数据的时候,会返回null;而load检索不到数据会返回org.hibernate.ObjectNotFoundException。下面通过两个例子来分析一下get与load的工作原理。
工作原理
Get加载(数据库中存在检索的数据),这里只分析测试类,实体类就不再讨论了。
/**
* 查询数据库中有数据的字段
*/
public void testGetNotNull() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
// 数据库中存在id为2的数据
User user = (User)session.get(User.class, 2);
System.out.println("---------Get加载--------");
System.out.println(user);
System.out.println(user.getId() + "---->>" + user.getName());
System.out.println("------------------------");
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
因为Hibernate规定get方法不能使用延迟加载,当执行到User user = (User)session.get(User.class, 2);这条语句时,get方法首先会查询session缓存,没有的话就查询二级缓存,最后会查询数据库,因此在执行该语句的时候,会先发出sql语句进行查询。而且,执行get方法的时候,get方法每次都会从数据库直接查询。由于这是数据库中存在id为2的数据,因此,user会返回实体对象。如下图:
Get加载(数据库中不存在检索的数据)
/**
* 查询数据库中不存在的数据
*/
public void testGetWithNull() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
// 数据库中不存在id为0的数据
User user = (User)session.get(User.class, 0);
System.out.println("---------Get加载--------");
System.out.println(user);
//System.out.println(user.getId() + "---->>" + user.getName());
System.out.println("------------------------");
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
同上,在执行到User user = (User)session.get(User.class, 0);这条语句时,get方法每次都是直接查询数据库,在执行该语句时,Hibernate会发出sql语句,到数据库进行查询数据,由于id为0的数据不存在,get方法查询不到数据时,会返回null。因此,user的结果自然也是null了。如下图:
Load加载(数据库中存在检索的数据)
/**
* 数据库中存在查询的数据
*/
public void testLoadNotNull() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
// 数据库中存在id为2的数据
User user = (User)session.load(User.class, 2);
System.out.println("----------Load加载-----------");
System.out.println(user);
System.out.println(user.getId() + "---->>" + user.getName());
System.out.println("-----------------------------");
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
Hibernate中,load方法是支持延迟加载的,在执行到User user = (User)session.load(User.class, 2);这条语句时,load方法首先会查找session的persistent Context中是否存在缓存,如果存在则直接返回;如果没有缓存,则load方法会判断是否是lazy加载,如果不是lazy方式,则直接访问数据库,查询Id为2的数据,由于数据库中存在Id为2的数据,因此get方法会返回实体对象。
如果load方法判断的是lazy方式加载,那么就需要建立代理对象,对象的initialized属性为false,target属性为null,在访问获得的代理对象的属性时,会访问数据库,找到记录后就会把该记录的对象复制到代理对象的target上,并将initialized属性设为true。在这个例子中,load方法采用的是lazy方式,因此在执行load方法时,Hibernate不会发出sql语句,因为此时Hibernate建立了代理对象,但并没有访问代理对象的属性。当执行System.out.println(user);时,Hibernate才会初次发出sql语句,去查询数据库。如下图:
Load加载(数据库中不存在检索的数据)
/**
* 数据库中不存在查询的数据
*/
public void testLoadWithNull() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
// 数据库中不存在id为0的数据
User user = (User)session.load(User.class, 0);
System.out.println("----------Load加载-----------");
System.out.println(user);
//System.out.println(user.getId() + "---->>" + user.getName());
System.out.println("-----------------------------");
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
同上,在执行到load方法时,load方法会首先查询session中是否存在缓存,如果存在则直接返回,如果不存在则会判断是否为lazy,这里设置的是lazy方式,因此load方法会认为数据库中存在数据,直接建立代理对象,把代理对象返回给user。
而执行到System.out.println(user);时,Hibernate会发出sql语句,访问数据库查询Id为0的数据,由于数据库中不存在Id为0的数据,因此load方法会返回org.hibernate.ObjectNotFoundException,直接抛出异常。如下图:
结束语
Hibernate中,对于get和load方法的根本区别,就在于Hibernate对于load方法认为数据库中一定存在要检索的数据,可以放心的使用代理来延迟加载,如果在使用过程中发现了问题,那么只能抛出异常;而对于get方法,Hibernate一定要获取到真实的数据才会返回对象,否则返回null。
参考资料:
后勤仓库的Hibernate get和load区别
分享到:
相关推荐
Dwr2+Struts2+Spring2.5+Hibernate3实战——用户登录注册系统
get方法首先查询session缓存,没有的话查询二级缓存,最后查询数据库;反而load方法创建时首先查询session缓存,没有就创建代理,实际使用数据时才查询二级缓存和数据库
自己研究的hibernate加载方式和多态加载的分析. 写的不好,不过可以供深入者确切体会hibernate的种种功能的本质
Hibernate 4——Hello World
NULL 博文链接:https://cici9898-007.iteye.com/blog/1847710
NULL 博文链接:https://ysj5125094.iteye.com/blog/1897557
NULL 博文链接:https://811417208-qq-com.iteye.com/blog/506950
一个整合了struts2和hibernate的简单例子,可实现对新闻的增删改查,支持新闻的模糊查找(标题与日期的结合查找)
struts2+Spring+Hibernate帮助文档_中文 struts2+Spring+Hibernate帮助文档_中文 struts2+Spring+Hibernate帮助文档_中文 struts2+Spring+Hibernate帮助文档_中文
Hibernate 的延迟加载(lazy load)是一个被广泛使用的技术。这种延迟加载保证了应用只有在需要时才去数据库中抓取相应的记录。通过延迟加载技术可以避免过多、过早地加载数据表里的数据,从而降低应用的内存开销。...
get和load方式是根据id取得一个记录 下边详细说一下get和load的不同,因为有些时候为了对比也会把find加进来。 1.从返回结果上对比: load方式检索不到的话会抛出org.hibernate.ObjectNotFoundException异常 get方法...
hibernate中get和load的区别共5页.pdf.zip
MyClipse6.0\Struts2,Spring与Hibernate整合应用,学生成绩管理系统
NULL 博文链接:https://quicker.iteye.com/blog/658451
Hibernate中根据Id单条查询获取对象的方式有两种,分别是get()和load(),来看一下这两种方式的区别。 1. get() 使用get()来根据ID进行单条查询: User user=session.get(User.class, "1"); 当get()方法被调用的时候...
7.1.1Hibernate的入门必备——文档和源码 视频看我的主页共享地方
简单的Hibernate实现Java通过多对多关联映射,进行学生课程管理。
hiberna 加载sql server所需的jar 文件