1:延迟加载就是延迟到真正需要数据的时候才加载,我第一次理解代理模式就是从这里开始的;
2:Hibernate中提供了对实体对象的延迟加载以及对集合的延迟加载,另外在Hibernate3中还提供了对属性的延迟加载

正文:
一:
1:如果想对实体对象使用延迟加载,必须要在实体的映射配置文件(hbm.xml)中进行相应的配置,如下所示:
<hibernate-mapping>
<class name=”com.neusoft.entity.User” table=”user” lazy=”true”>
通过将class的lazy属性设置为true,来开启实体的延迟加载特性

2:如果我们运行下面的代码:
User user=(User)session.load(User.class,”1”);(1)
System.out.println(user.getName());(2)
当运行到(1)处时,Hibernate并没有发起对数据的查询,如果我们观察此时user对象的内存快照,我们会惊奇的发现,此时返回的可能是User$EnhancerByCGLIB$$bede8986类型的对象,而且其属性为null,
这里所返回的对象实际上只是User对象的代理类对象。在Hibernate中通过使用CGLIB,来实现动态构造一个目标对象的代理类对象,并且在代理类对象中包含目标对象的所有属性和方法,而且所有属性均被赋值为null。
通过调试器显示的内存快照,我们可以看出此时真正的User对象,是包含在代理对象的CGLIB$CALBACK_0.target属性中,当代码运行到(2)处时,此时调用user.getName()方法,这时通过CGLIB赋予的回调机制,实际上调用CGLIB$CALBACK_0.getName()方法,当调用该方法时,Hibernate会首先检查CGLIB$CALBACK_0.target属性是否为null,如果不为空,则调用目标对象的getName方法,如果为空,则会发起数据库查询,生成类似这样的SQL语句:select * from user where id=’1’;来查询数据,并构造目标对象,并且将它赋值到CGLIB$CALBACK_0.target属性中。

3:这样,通过一个中间代理对象,Hibernate实现了实体的延迟加载,

只有当用户真正发起获得实体对象属性的动作时,才真正会发起数据库查询操作。所以实体的延迟加载是用通过中间代理类完成的,所以只有session.load()方法才会利用实体延迟加载,因为只有session.load()方法才会返回实体类的代理类对象。

如果使用get方法,则无论是否开启实体延迟加载机制,都会直接发起sql查询操作(立即加载)

4:在Hibernate的延迟加载机制中,针对集合类型的应用

我们在一对多(或多对多)关联中,定义的用来容纳关联对象的Set集合,并不是java.util.Set类型或其子类型,而是Hibernate自己的Set类型,通过使用自定义集合类的实现,Hibernate实现了集合类型的延迟加载
为了对集合类型使用延迟加载,我们必须在hbm文件中的set部分开启lazy机制,比如:
<set name=”addresses” table=”address” lazy=”true” inverse=”true”>

User user=(User)session.load(User.class,”1”);
Collection addset=user.getAddresses();       (1)
Iterator it=addset.iterator();                (2)
while(it.hasNext()){
Address address=(Address)it.next();
System.out.println(address.getAddress());
当程序执行到(1)处时,这时并不会发起对关联数据的查询来加载关联数据,只有运行到(2)处时,真正的数据读取操作才会开始,这时Hibernate会根据缓存中符合条件的数据索引,来查找符合条件的实体对象。

5:数据索引
在Hibernate中对集合类型进行缓存时,是分两部分进行缓存的,首先缓存集合中所有实体的id列表,然后缓存实体对象,这些实体对象的id列表,就是所谓的数据索引。
当查找数据索引时,如果没有找到对应的数据索引,这时就会一条select SQL的执行,获得符合条件的数据,并构造实体对象集合和数据索引,然后返回实体对象的集合,并且将实体对象和数据索引纳入Hibernate的缓存之中。
另一方面,如果找到对应的数据索引,则从数据索引中取出id列表,然后根据id在缓存中查找对应的实体,如果找到就从缓存中返回,如果没有找到,再发起select SQL查询
6:
在Hibernate3中,引入了一种新的特性——属性的延迟加载。比如,在User对象中有一个resume字段,该字段是一个java.sql.Clob类型,包含了用户的简历信息,当我们加载该对象时,我们不得不每一次都要加载这个字段,而不论我们是否真的需要它,而且这种大数据对象的读取本身会带来很大的性能开销。
在Hibernate3中,我们可以通过属性延迟加载机制,来使我们获得只有当我们真正需要操作这个字段时,才去读取这个字段数据的能力
<class name=”com.neusoft.entity.User” table=”user”>
<property name=”resume” type=”java.sql.Clob” column=”resume” lazy=”true”/>
    </class>
属性延迟加载需要字节码增强器的支持
二:
1:因为有了延迟加载,所以就有了lazyInitializationException,(也就是当你需要加载数据的时候,发现它的session关闭了),一个类从临时态(瞬时态)到持久态,再到游离态是通过是否纳入session管理来区分的,hibernate中的update为什么能更新数据呢,它是将游离的对象重新放回session管理中当然能更新数据了。如果我把持久态对象的数据改变了,是否必须要执行了save方法,这些自己去试一下就知道了,说到这里有点跑偏了,我们还是继续来说lazyInitializationException

2:解决延迟加载异常的方式
保证检索关联属性时,session必须开启
1)全局:把关系映射节点的lazy改为false----关闭延迟加载
2)局部:主动加载
  A:在DAO相应的方法session关闭之前强行使用关联对象,让其主动加载     getxxx()
  B:使用hibernate.initialize()方法,。。
3)DAO方法相互调用时,使用当前session的update方法,将游离态对象跟当前session关联起来
4)OpenSessionInView模式---延长hibernate session开启的时间,延长session关闭时间。把当前session跟当前用户请求绑定在一块。这时session的生命周期就跟一个request一致

方案4) 如图:

Hibernate延迟加载-by宋迪相关推荐

  1. 一些关于Hibernate延迟加载的误区

    最近面试别人,正好出的笔试题中有道关于Hibernate延迟加载的问题,聊天过程中发现很多人对Hibernate的延迟加载有些理解误区,写 些东东在这里,希望对大家有所帮助. 首先是第一个误区:延迟加 ...

  2. hibernate 延迟加载问题探讨

    延迟初始化错误是运用Hibernate开发项目时最常见的错误.如果对一个类或者集合配置了延迟检索策略,那么必须当代理类实例或代理集合处于持久化状态(即处于Session范围内)时,才能初始化它.如果在 ...

  3. hibernate 延迟加载(转载)

    http://blog.csdn.net/xc635960736/article/details/7049863(未找到原始的引文) Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默 ...

  4. IT忍者神龟之hibernate 延迟加载问题探讨

    关于   lazy   机制: 延迟初始化错误是运用   Hibernate   开发项目时最常见的错误.如果对一个类或者集合配置了延迟检索策略,那么必须当代理类实例或代理集合处于持久化状态(即处于S ...

  5. hibernate 延迟加载

    Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认也会被延迟加载.Hibernate 通过这种延迟加载来降低系统的内存开销,从而保证 Hiberna ...

  6. hibernate延迟加载(get和load的区别)

    在hibernate中我们知道如果要从数据库中得到一个对象,通常有两种方式,一种是通过session.get()方法,另一种就是通过session.load()方法,然后其实这两种方法在获得一个实体对 ...

  7. hibernate延迟加载lazy的原理,以及为什么session关闭会报错

    2019独角兽企业重金招聘Python工程师标准>>> 通过将class的lazy属性设置为true,来开启实体的延迟加载特性. 如果我们运行下面的代码: User user=(Us ...

  8. Hibernate延迟加载

    1.类级别的延迟加载 1.     是通过session.load方法实现的      在映射文件中:       <class name="cn.itcast.hibernate71 ...

  9. hibernate延迟加载(get和load的区别)(转)

    在hibernate中我们知道如果要从数据库中得到一个对象,通常有两种方式,一种是通过session.get()方法,另一种就是通过session.load()方法,然后其实这两种方法在获得一个实体对 ...

最新文章

  1. 机器学习算法选择——特征提取
  2. Windows 10 install Pycharm 开发环境
  3. webpack window 添加第三方库
  4. 软件使用: word
  5. 计算机专业博士发论文,计算机专业本科、硕士、博士学位论文编写方法浅析
  6. p20pro 鸿蒙,后置镜头变液态双摄?华为P50Pro再曝光,搭载鸿蒙OS传感器变1寸
  7. js将文字填充与canvas画布再转为图片
  8. CodeProject上的最近几篇关于IronPython技术的文章
  9. codeforces1437 E. Make It Increasing——最长上升子序列
  10. 你胆敢不加break试试?
  11. 32张感恩海报!武汉市文化和旅游局这波操作太可以了
  12. ER图和关系模型到MySQL数据库表
  13. 驱动开发中的常用操作
  14. matelab中simulink报错改正方法
  15. mysql btree面试_java面试题:你了解mysql的B+TREE索引吗?
  16. win98访问win7方法
  17. PostgreSQL如何导入SJIS字符集的文件
  18. 【ARM】嵌入式 ARM Linux 下移植 USB 蓝牙、交叉编译 bluez 各种版本
  19. 音视频开发之Android端native层播放音频三种方式
  20. [ZT]留学美、英、加、法必读

热门文章

  1. 51单片机数字时钟套件 DIY散件
  2. Linux上接收广播
  3. 计算机名称在用户还是旧的,计算机名称改了以后如何找回原来的名字 ?
  4. MATLAB读取excel表格中指定位置的数据
  5. python实现图书管理系统(完善版)
  6. 《果然新鲜》电商项目(44)- 利用Logstash自动同步数据库内容到ES
  7. 禁毒海报|国际禁毒日海报素材图片大全
  8. python统计英文文章中单词的个数无文件_求Python统计英文文件内单词个数的思路...
  9. SpringBoot使用爬虫(初级阶段)
  10. 为什么建议大家使用 Linux 开发?真的很很很优雅!