关于懒加载

在关系数据库设计的时候,我们很多时候把表之间的关系设置为强关联(使用外键进行约束),在Hibernate中利用对象的包含关系进行维护(HIbernate本身就是面向对象的数据库操作模式),例如class有很多student,我们在查询class的时候如果我们把class对应的student都查询出来,student很多的话效率是很低的,但是我们并不会用到class对应的student,这个时候我们希望不去查询student,只有在用到的时候再去查询。这就是Hibernate的懒加载存在的原因——不立即去查询数据库,先使用一个代理对象,在用到的时候再去查询数据库(如果对应的Session还open的话)。

在进行详细介绍之前,先理解一下代理:

代理:Hibernate动态生成的一个类,继承自需要代理的实体类,所以如果实体类要用到懒加载就不能声明为final的。

优点:

减少不必要的查询,提高与数据库交互的效率

缺点:

在使用懒加载后,如果我们需要把student返回前台,但是这个时候session已经关闭,Hibernate不能根据代理对象查询数据库,这个时候再使用student的时候会报LazyInitializationException。

懒加载的配置

lazy(指定抓取时机,什么时候去数据库查询)

用在<class>标签上(只是说明在使用load本类的时候的加载策略):

  • true:默认的取值,使用懒加载
  • false:不使用懒加载

用在<set>、<list>上

  • true:默认取值,使用到该集合里面的元素时才查询
  • false:不使用懒加载,直接查询
  • extra:如果调用的是size/contains方法的时候不去查询,在真正使用里面的元素的时候才查询

用在<one-to-one>和<many-to-one>上

  • false:不使用懒加载策略
  • proxy:默认取值,在使用到的时候才进行查询
  • no-proxy:(很少使用,需编译时期字节码增强)在使用到关联对象的属性(或者其get、set方法)的时候才会查询,使用关联对象的普通方法的时候不会查询,但是编译的时候需要字节码增强(就是在类进行编译的时候使用一定方式增加类的字节码,用来丰富字节码的内容,增强字节码以实现特定的功能,比如我们这儿生成可供hibernate 进行懒加载所需要的功能,编译时期增强字节码的方式有:JVM代理,第三方类加载器),例如


  1. class Person{

  2. private Card card = null;

  3. // setter& getter

  4. }
  5. class Card{

  6. private String number;

  7. // setter & getter

  8. public void upgrade(){

  9. // TODO

  10. }

  11. }

  12. class Test{

  13. public static void main(String[] args){

  14. Person p = (Person)session.get(Person.class, 1);

  15. // 会访问数据库

  16. p.getCard().getNumber();

  17. // 不会访问数据库

  18. p.getCard().upgrade();

  19. }

  20. }
class Person{
private Card card = null;
// setter& getter
}

class Card{
private String number;
// setter & getter
public void upgrade(){
// TODO
}
}
class Test{
public static void main(String[] args){
Person p = (Person)session.get(Person.class, 1);
// 会访问数据库
p.getCard().getNumber();
// 不会访问数据库
p.getCard().upgrade();
}
}

fetch(指定抓取方式,怎么查询数据)

  • join:使用表连接的方式抓取,使用join的时候lazy配置失效
  • select:查询的时候另外发送一条select语句

出现懒加载的情况

使用load单个对象,这个对象会被懒加载

比如session.get(student.class, 1),student会被懒加载,使用getId的时候不回去查询数据库,因为id是由Hibernate维护的

使用<one-to-one>

查询主对象,默认使用join进行连接查询,不使用懒加载,

查询从对象默认使用懒加载,先发送一条select查询从对象,在使用到的时候再发送一条select查询主对象

使用<many-to-one>

查询多的一方的时候使用懒加载(使用Hibernate的时候,而不是JPA)

使用<set>/<list>

默认使用懒加载

懒加载问题解决

在开始的时候我们说了懒加载出现的问题,下面给出三种懒加载的解决方案

方法一:使用Hibernate.initialize(object)

在session未关闭之前调用该方法初始化想要加载的对象,例如

Hibernate.initialize(student);

Hibernate.initialize(student.getCourses());

方法二:重新关联到session

当对象处于脱管的状态,使用lock方法重新关联到session,转化为持久态



  1. //直接重新关联

  2. session.lock(object, LockMode.NONE);

  3. //进行版本检查后关联

  4. session.lock(object, LockMode.READ);

  5. //使用SELECT ... FOR UPDATE进行版本检查后关联

  6. session.lock(object, LockMode.UPGRADE);
//直接重新关联
session.lock(object, LockMode.NONE);
//进行版本检查后关联
session.lock(object, LockMode.READ);
//使用SELECT ... FOR UPDATE进行版本检查后关联
session.lock(object, LockMode.UPGRADE);

方法三:使用OPenSessionInView

OpenSessionInViewFilter一个filter,这个filter把session绑定到当前请求线程上,只要在请求的生命周期内,就可以访问懒加载的对象。配置:



  1. <filter>

  2. <filter-name>hibernateOpenSessionInViewFilter</filter-name>

  3. <filter-class>org.springside.modules.orm.hibernate.OpenSessionInViewFilter</filter-class>

  4. <init-param>

  5. <param-name>flushMode</param-name>

  6. <param-value>AUTO</param-value>

  7. </init-param>

  8. </filter>

  9. <filter-mapping>

  10. <filter-name>hibernateOpenSessionInViewFilter</filter-name>

  11. <url-pattern>/*</url-pattern>

  12. </filter-mapping>
<filter>
<filter-name>hibernateOpenSessionInViewFilter</filter-name>
<filter-class>org.springside.modules.orm.hibernate.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>flushMode</param-name>
<param-value>AUTO</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>hibernateOpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

参考:

http://www.cnblogs.com/linbaoji/archive/2009/01/07/1370919.html

http://blog.csdn.net/yaorongwang0521/article/details/7074573

特别感谢以上文章的作者,如若有冒犯或者侵权的地方,请及时联系本人修改。

web进修之—Hibernate 懒加载(6)的更多相关文章

  1. 关于s2sh框架关于hibernate懒加载问题的说明和解决方案

    首先我们来看下面这个图,解释了一个web程序的一次请求流程! 懒加载异常的说明: 懒加载就是我们在查询一个对象时,它所有的属性是否要被查出来! 如果懒加载开启的话,session在service层就被 ...

  2. 关于Hibernate懒加载问题的最终解决方案

    看到一篇Hibernate懒加载的文章,所以转载,原地址如下: http://tuoxie007.iteye.com/blog/334853 Hibernate的强大之处之一是懒加载功能,可以有效的降 ...

  3. 【转】hibernate懒加载的问题,failed to lazily initialize a collection of role

    hibernate懒加载的问题,failed to lazily initialize a collection of role hibernate懒加载的问题,failed to lazily in ...

  4. Hibernate懒加载导致json数据对象传输异常的问题---(非常重要)

    1. 异常: [console_demo][WARN] [2016-12-15 19:49:35] org.springframework.web.servlet.mvc.support.Defaul ...

  5. hibernate懒加载(转载)

    http://blog.csdn.net/sanjy523892105/article/details/7071139 懒加载详解 懒加载为Hibernate中比较常用的特性之一,下面我们详细来了解下 ...

  6. Hibernate懒加载的三种解决方案

    Hibernate懒加载的两种解决方案: 1.Hibernate.initialize(代理对象) 2.在*.hbm.xml映射文件中添加lazy="false"属性 3.使用op ...

  7. Hibernate懒加载解析

    Hibernate懒加载解析 在Hibernate框架中,当我们要访问的数据量过大时,明显用缓存不太合适, 因为内存容量有限 ,为了减少并发量,减少系统资源的消耗,这时Hibernate用懒加载机制来 ...

  8. hibernate懒加载

    Hibernate懒加载解析 hibernatejoinsession数据库sqlobject Hibernate懒加载解析 在Hibernate框架中,当我们要访问的数据量过大时,明显用缓存不太合适 ...

  9. Hibernate懒加载深入分析

    Hibernate懒加载深入分析 懒加载可以提高性能吗?  不可以简单的说"能",因为Hibernate的关系映射拖累了SQL的性能,所以想出懒加载来弥补.只是弥补而以,不会超越. ...

随机推荐

  1. Codeforces 884 简要题解

    文章目录 A题 B题 C题 D题 E题 F题 传送门 A题 传送门 题意简述: 一个人要完成一件事总共需要ttt秒,现在有nnn天,每天有aia_iai​不能做事,问他可以在第几天做完. 思路:按照题 ...

  2. angular 实现 echarts 拖动区域进行放大 方法

    实现逻辑: 1.通过鼠标摁下事件  和弹出事件  获取x轴的index  之后去x轴的list中去获取两个坐标点 2.之后将这两个数据作为参数  传到后台更新数据 3.记录下来这两个坐标点 放到lis ...

  3. Exp3 免杀原理与实践_05齐帅

    Exp3 免杀原理与实践 20154305_齐帅 想要弄懂免杀,一定得先把基础问题弄明白啊~~ 一.基础问题回答 (1)杀软是如何检测出恶意代码的? - -检测特征码: 依靠分析总结出计算机病毒中常出 ...

  4. APIView源码简单分析图

    APIView源码简单分析 !声明:下面这个dispatch分发方法不在是父类View里的dispatch了,APIView重新封装了这个dispatch.(整个核心就是initialize_requ ...

  5. 你可能不知道的web api

    简介 作为前端工作者,我们的工作与web是分不开的,随着HTML5的日益壮大,浏览器自带的webapi也随着增多.本篇文章主要选取了几个有趣且有用的webapi进行介绍,分别介绍其用法.用处以及浏览器 ...

  6. influence maximization

    Robust Influence Maximization 首先简要介绍一下这个问题:在一个社交网络图中寻找固定数量的节点,使得这些节点对所有节点的影响值尽可能的大.这个问题由于在病毒式营销,谣言监控 ...

  7. 【repost】javascript callback

    在javascript中回调函数非常重要,它们几乎无处不在.像其他更加传统的编程语言都有回调函数概念,但是非常奇怪的是,完完整整谈论回调函数的在线教程比较少,倒是有一堆关于call()和apply() ...

  8. vue watch高级用法

    watch是vue组件最常用,最重要的功能之一,我们都知道它最基本的特性就是监听的data对象里的属性变化了,watch就会自动执行. 那它还有什么骚操作呢?下面我带大家看看,菜鸟一枚,如有错误欢迎指 ...

  9. 转 Tomcat+redis+nginx配置

    为客户开发的一个绩效系统,采用了java web的开发方式,使用了一些spring mvc, mybatis之类的框架.相比于oracle ebs的二次开发,这种开发更加灵活,虽然和ebs集成的时候遇 ...

  10. MIPS汇编指令集

    MIPS有三种指令格式: R型 6 5 5 5 5 6 op rs rt rd shamt funct 功能:寄存器-寄存器ALU操作 (算术运算,逻辑运算) I型 6 5 5 16 op rs rt ...