Hibernate懒加载深入分析

懒加载可以提高性能吗? 

不可以简单的说"能",因为Hibernate的关系映射拖累了SQL的性能,所以想出懒加载来弥补.只是弥补而以,不会超越.所以大家不要想着使用了懒加载总体性能就提高了,其实总体性能不下降就万幸了.

懒加载为Hibernate中比较常用的特性之一,下面我们详细来了解下懒加载的原理和注意事项

Load()方法的懒加载原理

在Hibernate中,查询方法有两个,分别是get()和load(),这两种方法的不同就是load()拥有懒加载的特性。Load()方法就是在查询某一条数据的时候并不会直接将这条数据以指定对象的形式来返回,而是在你真正需要使用该对象里面的一些属性的时候才会去数据库访问并得到数据。他的好处就是可以减少程序本身因为与数据库频繁的交互造成的处理速度缓慢。

以一个Person类做例子,我们写一个查询的方法如下:

public static void query(int id){
Session session=null;
try{
session=HibernateUtil.getSession();
Person person=(Person) session.load(Person.class, id);
//System.out.println(person.getName());
}catch(HibernateExceptionex){
ex.printStackTrace();
}finally{
if(session!=null){
session.close();
}
}
}

然后在Hibernate配置文件中添加以下属性

<property name="hibernate.show_sql">true</property> 

这条属性的作用为将Hibernate运行时产生的每一条SQL语句都打印出来

运行上述方法后,我们并没有看到Hibernate打印任何查询语句,这时我们可以将注释的语句重新调回来,让他打印查询到的person的name。这时我们可以看到Hibernate产生的查询语句并看到person的name属性。这就是懒加载了。

那么在Hibernate懒加载的时候,返回的对象是空的吗?答案是否定的,我们可以通过打印person.getClass()方法来验证,打印出来的结果并不是null,而是一个Person后面加了一堆很奇怪的字符的类。可以肯定的是懒加载的对象并不是空,而且这个对象的类型不是Person类。那么他到底是什么呢?

其实这个兑现我们管它叫做代理对象,而这个对象所属的类是Person类的子类,是Hibernate自动实现的一个子类。这个子类的特点是:当你访问person对象的某一个属性的时候,他会自动查询数据库中对应这个对象的数据并返回,这就是为什么在创建对象关系映射的时候要求实体类不能够为final类型的原因了。

但是这个对象是有一个生命周期的,我们可以改写上述方法如下:

public static Person query(int id){
Session session=null;
Person person=null;
try{
session=HibernateUtil.getSession();
person=(Person)session.load(Person.class, id);
//System.out.println(person.getName());
}catch(HibernateExceptionex){
ex.printStackTrace();
}finally{
if(session!=null){
session.close();
}
}
return person;
}

调用这个方法并返回查询到的代理对象,我们可以在返回该对象后打印该对象的name属性,这时会抛出一个org.hibernate.LazyInitializationException异常

这就是懒加载不能初始化异常,这就说明了一件事,懒加载的时候如果想通过代理对象查询数据库,需要在该session关闭以前才可以。但如果一定要在session关闭以后再使用代理对象的话,Hibernate中定义了一个初始化代理对象的方法initialize(),通过该方法即可将代理对象初始化。

注:在使用代理对象的getId()方法和getClass()方法的时候,并不会抛出不能初始化异常,因为这两个属性并不用查询数据库。

懒加载可以用于关系映射和集合属性的操作,而且懒加载是可以关闭并打开的,下面我们会根据不同的情况分析一下懒加载。

一对一的懒加载分析

一对一的懒加载并不常用,因为懒加载的目的是为了减少与数据库的交互,从而提高执行效率,而在一对一关系中,主表中的每一条数据只对应从表的一条数据库,就算都查询也不会增加多少交互的成本,而且主表不能有contrained=true,所以主表是不能懒加载的。(从表可以有)

注:当fetch设置为join时,懒加载就会失效。因为fetch的作用是抓取方式,他有两个值分别问select和join,默认值为select。即在设为join时,他会直接将从表信息以join方式查询到而不是再次使用select查询,这样导致了懒加载的失效。

一对多和多对多的懒加载分析

与一对一关联不同,一对多和一对多的关联下,主表的每一条属性都会对应从表的多条数据,这个时候懒加载就显得非常有效了。比如一个部门里面有多个员工,如果没有懒加载,每查询这个部门的时候都会查询出多个员工,这会大大增加与数据库交互的成本。所以Hbernate默认的是加入懒加载的。这就是查询集合属性的时候返回的是一个PersistentIndexed*类型对象的原因。该对象其实就是一个代理对象。当然,可以在映射文件中通过将lazy属性设为假来禁用。

多对一的懒加载分析

虽然多对一与一对一关系方式相同,但是在Hibernate中多对一时,默认是进行懒加载的。另外有一点需要注意的是懒加载并不会区分集合属性里面是否有值,即使是没有值,他依然会使用懒加载,这也是懒加载不够完善的地方之一。

 

懒加载的一些细节扩充

有的时候,我们在session关闭后仍需要使用懒加载的代理对象来查询数据库,这时我们就需要将代理对象初始化,不过问题是,当我们不能确定初始化后就一定使用该对象的时候怎么办,这样不是又白白浪费了资源吗?我们可以在使用代理对象的方法里面加入一个布尔值参数,这样当我们不需要初始化代理对象的时候只要将布尔参数设为假。但也是有缺点的,因为在调用的时候,尤其是在别人使用的时候,参数越多,方法学习成本就会增加,所以请酌情处理。

懒加载也可以用于某些简单属性,但是因为实现起来比较复杂,而且效果并不明显,所以并不推荐。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Hibernate懒加载深入分析的更多相关文章

  1. 转 : Hibernate懒加载深入分析

    懒加载可以提高性能吗? 不可以简单的说"能",因为hibernate的关系映射拖累了SQL的性能,所以想出懒加载来弥补.只是弥补而以,不会超越.所以大家不要想着使用了懒加载总体性能 ...

  2. hibernate懒加载(转载)

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

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

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

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

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

  5. Hibernate懒加载解析

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

  6. hibernate懒加载

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

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

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

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

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

  9. -java转json hibernate懒加载造成的无限递归问题

    1.在判断到底是谁维护关联关系时,可以通过查看外键,哪个实体类定义了外键,哪个类就负责维护关联关系. JoinColumn(name="pid") 2. 在保存数据时,总是先保存的 ...

随机推荐

  1. Windows 上 GitHub Desktop 的操作

    目 录 第1章 上传开源代码至GitHub    1 1.1 git Windows 客户端    1 1.2 注册GitHub账户    2 1.3 登录    2 1.4 创建本地代码仓库     ...

  2. Linux系统的方法论

    Linux系统的方法论 https://www.cnblogs.com/youxia/p/LinuxDesktop001.html 阅读目录 特别说明 什么情况下适合玩Linux桌面 Linux桌面系 ...

  3. flask logging 最佳实践

    flask项目中, 你可以使用python 的 logging模块实现记录日志. 也可以使用 flask 基于logging模块封装过的app.logger实现. 直接上代码 config.py im ...

  4. relative和absolute

    relative 相对定位 1. 幻影瞬移 absolute属性也有瞬移技能,不同之处在于:absolute属性以天空或其他外界限制计算瞬移位置:而relative属性由于是凡人肉体,偏移能力有限,只 ...

  5. View Programming Guide for iOS ---- iOS 视图编程指南(五)---Animations

      Animations Animations provide fluid visual transitions between different states of your user inter ...

  6. 时间戳 js 转换

    // 获取当前时间戳(以s为单位) var timestamp = Date.parse(new Date()); timestamp = timestamp / 1000; //当前时间戳为:140 ...

  7. js、匿名函数、闭包、回调函数

    234567891011121314151617181920212223242526272829303132333435 闭包 闭包:闭包是指有权访问另一个函数作用域中的变量的函数 函数嵌套一个函数, ...

  8. https://www.luogu.org/blog/An-Amazing-Blog/mu-bi-wu-si-fan-yan-ji-ge-ji-miao-di-dong-xi

    https://www.luogu.org/blog/An-Amazing-Blog/mu-bi-wu-si-fan-yan-ji-ge-ji-miao-di-dong-xi

  9. Cg profiles,如何使用CGC编译Cg语言(转)

    抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人” 计算机只能理解和执行由0.1序列(电压序列 ...

  10. IT兄弟连 Java Web教程 经典案例2

    案例需求:写一个用户登录的html页面有账号和密码,并在登录的Servlet中获取登录的账号和密码,如果账号是abc密码是123则向浏览器输出登录成功,否则向浏览器输出登录失败. 案例实现: ●  h ...