Hibernate之lazy延迟加载
一.延迟加载的概念
当Hibernate从数据库中加载某个对象时,不加载关联的对象,而只是生成了代理对象,获取使用session中的load的方法(在没有改变lazy属性为false的情况下)获取到的也是代理对象,所以在上面这几种场景下就是延迟加载。
二.理解立即加载的概念
当Hibernate从数据库中加载某个对象时,加载关联的对象,生成的实际对象,获取使用session中的get的方法获取到的是实际对象。
三.为什么要使用延迟加载
延迟加载策略能避免加载应用程序不需要访问的关联对象,以提高应用程序的性能。
四.立即加载的缺点
Hibernate在查询某个对象时,立即查询与之关联的对象,我们可以看出这种加载策略存在两大不足:
1.select的语句数目太多,需要频繁的访问数据库,会影响查询的性能。
2.在应用程序只需要访问要的对象,而不需要访问与他关联的对象的场景下,加载与之关联的对象完全是多余的操作,这些多余的操作是会占内存,这就造成了内存空间的浪费。
五.什么时候使用延迟加载什么时候使用立即加载
如果程序加载一个持久化对象的目的是为访问他的属性,则可以采用立即加载。如果程序加载一个持久化对象的目的仅仅是为了获得他的引用,则可以采用延迟加载。
六.Hibernate在对象-关系映射问价中配置加载策略
I.类级别:
<class>元素中lazy属性的可选值为true(延迟加载)和false(立即加载);
<class>元素中的lazy属性的默认值为true
II.一对多关联级别:
<set>元素中的lazy属性的可选值为:true(延迟加载),extra(增强延迟加载)和false(立即加载);
<set>元素中的lazy属性的默认值为true
III.多对一关联级别:
<many-to-one>元素中lazy属性的可选值为:proxy(延迟加载),no-proxy(无代理延迟加载)和false(立即加载)
<many-to-one>元素中的lazy属性的默认值为proxy
在下面的一些案例中都会以员工(Emp)的部门(Dept)的例子讲解:
员工和部门是多对一的关系:
关于员工和部门的Hibernate配置就不啰嗦了:可以看我的这篇博客:http://www.cnblogs.com/heyongjun1997/p/5767187.html
I.1类级别的查询策略:
01.立即加载案例:
需求:通过Session的load()方法加载Dept对象时:
首先在Dept.hbm.xml文件中配置lazy属性为false,表示立即加载。
@Test public void loadDept() { // 获取Session对象 Session session = HibernateUtil.currentSession(); // 如果通过load方式加载Dept对象 Dept dept=(Dept)session.load(Dept.class, 12); // 关闭session HibernateUtil.closeSession(); }
我们知道使用Load方法加载的是代理对象,只会在属性里保存一个OID,但是如果在Dept映射文件中配置了类级别的lazy为false就代表加载该对象时立即加载,也就是立即检索一道数据库,发出sql:
02.延迟加载案例:
同样是获取Dept对象,但是要把Dept.hbm.xml配置文件的类级别的lazy属性改为lazy=”true” 或者不写,应为类级别的lazy属性默认就是true,
@Test public void loadDept() { // 获取Session对象 Session session = HibernateUtil.currentSession(); // 如果通过load方式加载Dept对象 session.load(Dept.class, 12); // 关闭session HibernateUtil.closeSession(); }
此时Dept.hbm.xml配置文件的类级别的lazy属性为true,则是延迟加载,那么load方法获取的知识Dept的代理对象,所以他不会去检索数据库。
II.1一对多和多对多关联的查询策略
01.立即加载案例:
在获取部门对象的时候同时获取员工对象:
设置Dept.hbm.xml 类级别的lazy属性为false;表示立即加载:
设置<set>元素的lazy属性为false,表示在加载部门的同时立即加载员工:
@Test public void loadDept() { // 获取Session对象 Session session = HibernateUtil.currentSession(); // 如果通过load方式加载Dept对象 Dept dept=(Dept)session.load(Dept.class, 12); // 关闭session HibernateUtil.closeSession(); }
控制台输出结果:
当你想获取一的一方(Dept)的对象同时,你也要加载多的一方(Emp)的对象,那么你要在一的一方(Emp)的<set>的节点上加上lazy="false"表示立即加载,所以在使用Load方式加载Dept对象的时候,Emp对象也会不加载出来,所以程序在运行到Dept dept=(Dept)session.load(Dept.class, 12);会发出两条sql语句:
第一条是查询部门的信息,第二条sql是根据部门编号去数据库中检索员工信息。
02.延迟加载:
如果把上面的案例<set>节点的属性lazy改为trur,或者默认不写,那么在加载Dept对象的时候,就不会再去加载Emp对象,而且只会发出一条sql,这条sql就是指检索部门的信息。
03.增强延迟加载:
当<set>元素中配置lazy的属性为extra,表明是增强延迟加载策略。
其实增强延迟加载策略与一般的延迟加载策略lazy="true"非常相似。他们主要区别在于,我们看到这个名词增强延迟加载,顾名思义就是这个策略能在进一步的帮我延迟加载这个对象,也就是代理对象的初始化时机。
演示案例:
01. 当set节点的lazy属性为true,或者不写的话(取默认值),那么执行以下语句:
@Test public void loadDept() { // 获取Session对象 Session session = HibernateUtil.currentSession(); // 如果通过load方式加载Dept对象 Dept dept=(Dept)session.load(Dept.class, 12); //拿该部门下的员工的人数:也就是集合的大小 dept.getEmps().size(); // 关闭session HibernateUtil.closeSession(); }
输出结果:
02. 当set节点的lazy属性为extra那么执行以下语句:
@Test public void loadDept() { // 获取Session对象 Session session = HibernateUtil.currentSession(); // 如果通过load方式加载Dept对象 Dept dept=(Dept)session.load(Dept.class, 12); //拿该部门下的员工的人数:也就是集合的大小 dept.getEmps().size(); // 关闭session HibernateUtil.closeSession(); }
输出结果:
III.1多对一关联的查询策略
在映射文件中,<many-to-one>元素用来设置多对一的关系,在Emp.hbm.xml文件中表明Emp类到Dept类的多对一的关联关系:
01.延迟加载
需求:获取Emp对象,但是并不去加载与之关联的Dept对象。
首先要设置<many-to-one>节点的lazy属性为proxy,表示延迟加载。
@Test
public void loadEmp() {
// 获取Session对象
Session session = HibernateUtil.currentSession();
// 如果通过load方式加载Dept对象
Emp emp=(Emp)session.get(Emp.class, 1);
//获取Dept对象,因为此时的配置文件lazy是proxy,所以是代理对象
Dept dept=emp.getDept();
// 关闭session
HibernateUtil.closeSession();
}
控制台输出结果:
结果大家可想而知:<many-to-one>节点的lazy属性为proxy,表示延迟加载。在加载Emp对象的时候会发出sql去查询数据库,但是在获取Dept对象的时候延迟加载了,所以不会发出sql。
02.无代理延迟加载:
在<many-to-one>元素中配置lazy属性为no-proxy,表示无代理延迟加载。
@Test public void loadEmp() { // 获取Session对象 Session session = HibernateUtil.currentSession(); // 如果通过load方式加载Dept对象 Emp emp=(Emp)session.get(Emp.class, 1); //获取Dept对象,因为此时的配置文件lazy是proxy,所以是代理对象 Dept dept=emp.getDept(); // 关闭session HibernateUtil.closeSession(); }
此程序在加载的Emp对象dept属性为NULL,当程序运行到第3行的时候将触发Hibernate执行查询Dept表的select语句,,从而加载Dept对象,由此可见,当lazy属性为proxy时,可以延长延迟加载Dept代理对象的时间,而lazy属性为no-proxy时,则可以避免使用由Hibernate提供的Dept代理类实例,是Hibernate对程序提供更加透明的持久化服务。
03.立即加载:
首先要设置<many-to-one>节点的lazy属性为false,表示立即加载。
@Test
public void loadEmp() {
// 获取Session对象
Session session = HibernateUtil.currentSession();
// 如果通过load方式加载Dept对象
Emp emp=(Emp)session.get(Emp.class, 1);
//获取Dept对象,因为此时的配置文件lazy是false,所以是实际对象
Dept dept=emp.getDept();
// 关闭session
HibernateUtil.closeSession();
}
控制台输出结果:
Hibernate之lazy延迟加载的更多相关文章
- Hibernate之lazy延迟加载(转)
一.延迟加载的概念 当Hibernate从数据库中加载某个对象时,不加载关联的对象,而只是生成了代理对象,获取使用session中的load的方法(在没有改变lazy属性为false的情况下)获取到的 ...
- Hibernate中的延迟加载及fetch
Hibernate中的延迟加载 1.类级别的查询策略: lazy : true(默认值) false(立即加载) 2.多对一关联的查询策略: lazy: proxy(默认值) no-proxy ...
- Hibernate是如何延迟加载的
Hibernate是如何延迟加载的 2011-12-24 13:58 242人阅读 评论(0) 收藏 举报 hibernatespringinterceptordao数据库integer Hibern ...
- hibernate中lazy的使用
lazy,延迟加载 Lazy的有效期:只有在session打开的时候才有效:session关闭后lazy就没效了. lazy策略可以用在: * <class>标签上:可以取值true/fa ...
- Hibernate学习之延迟加载
转自:http://www.cnblogs.com/xiaoluo501395377/p/3371776.html 在hibernate中我们知道如果要从数据库中得到一个对象,通常有两种方式,一种是通 ...
- (十六)Hibernate中的延迟加载
一.什么是延迟加载 为了节省Hibernate加载对象的性能节销,在Hibernate中真正需要用到这个对象时,才会发出 SQL语句来抓取这个对象.这一个过程称为延迟加载. 二.延迟加载 ...
- Lazy 延迟加载
问题:最近遇到一个项目遇到一个问题(很久的项目,现阶段主要维护),程序初始化的时候比较慢,最后查原因的时候发现是因为一个类的构造方法里面有些逻辑, 解决办法:希望在使用的时候再进行加载,最后想到了延迟 ...
- 【Hibernate】浅析hibernate中的延迟加载
1 简介 在使用一些查询方法时,方法执行了,但是并没有立刻发送SQL语句查询数据库.而是在访问对象的getXxx方法时候才触发SQL执行加载对象数据.这种机制就称为延迟加载. 2 优点 延迟加载主要是 ...
- AutoWired注解和Lazy延迟加载
一.代码截图: @Lazy是延迟加载的意思, 容器启动时不创建对象, 当从容器中需要获取此对象时才创建. @Lazy//@Lazy注解可以用在类上, 还可以用在普通方法上,还可以用在构造方法上,还可以 ...
随机推荐
- [No000092]SVN学习笔记3-Import/Checkout(迁入/迁出),GetLock(加锁)
一.TortoiseSVN Client 获取服务器端的文件到新的本地文件夹 1.在本地新文件夹上右键菜单: 2.打开Repo-browser(可能需要输入你的用户名&密码) 3.输入服务器端 ...
- python框架之django
python框架之django 本节内容 web框架 mvc和mtv模式 django流程和命令 django URL django views django temple django models ...
- HTML 学习笔记 (drag & drop)
拖放(Drag & Drop)是一种常见的特性,即抓取对象以后拖到另一个位置.在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放.过去,我们用监听鼠标的Mousedown.Mouseo ...
- Less:优雅的写CSS代码
css是不能够定义变量的,也不能嵌套.它没有编程语言的特性.在项目开发中,常常发现有很多css代码是相同的,但我们通常都是复制然后粘贴. 举个例子:假设h5应用里主题色是#FF3A6D,可能用于文字或 ...
- 两年来的core折腾之路几点总结,附上nginx启用http2拿来即用的配置
序:一年多没更新博客园的内容了,core已经发生了翻天覆地的变化,想起2014年这时候,我就开始了从当时还叫k的那套preview都不如的vnext搭建这套系统,陆陆续续它每一次升级,我也相应地折腾, ...
- MVC跨域CORS扩展
一般的基于浏览器跨域的主要解决方法有这么几种:1.JSONP 2.IFrame方式 3.通过flash实现 4.CORS跨域资源共享 ,这里我们主要关注的是在MVC里面的CORS ...
- Redis系列之(二):Redis主从同步,读写分离
1. Redis主从同步 Redis支持主从同步.数据可以从主服务器向任意数量的从服务器上同步,同步使用的是发布/订阅机制. 2. 配置主从同步 Mater Slave的模式,从Slave向Maste ...
- 表单验证插件之jquery.validate.js
提到表单验证的插件,第一个想到的就是jquery.validate.js,所以小生想在这里稍微详细地说一下这款插件的具体使用方法,便于理解,我直接附上整段demo的代码(没怎么调样式,主要是看js): ...
- android studio 使用jar包,arr包和怎么使用githup开源项目中的aar包或module
我这里的android studio的版本是2.2.3版本 一.现在大家都用android studio了,就有人问怎么使用jar包 其实使用jar包比较简单 直接吧jar放入工程的app目录下的li ...
- 【BZOJ-3881】Divljak AC自动机fail树 + 树链剖分+ 树状数组 + DFS序
3881: [Coci2015]Divljak Time Limit: 20 Sec Memory Limit: 768 MBSubmit: 508 Solved: 158[Submit][Sta ...