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

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

(10) Hibernate懒加载详解相关推荐

  1. Hibernate懒加载解析

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

  2. hibernate 懒加载_Hibernate懒/急加载示例

    hibernate 懒加载 这篇文章将重点讨论为什么以及如何在应用程序中使用称为LAZY和EAGER加载的概念,以及如何使用Spring的Hibernate模板以EAGER方式加载LAZY实体. 当然 ...

  3. Android Loader 异步加载详解二:探寻Loader内部机制

    Android Loader 异步加载详解二:探寻Loader内部机制 转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/7025991 ...

  4. Android Loader 异步加载详解一:基础概念

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/70241844 本文出自[赵彦军的博客] Android Loader 异步加载详解 ...

  5. Hibernate懒加载问题

    刚开始接触这种数据持久化框架时,使用的是Maybatis,相较于最原始的JDBC+SQL模式,Maybatis简直就是神器,特别是在用过Maybatis动态SQL后,简直就开始对Maybatis爱不释 ...

  6. Hibernate懒加载问题的5种解决方案

    ** 1.Hibernate基础 ** Hibernate基础,传送门 ** 2.什么是Hibernate懒加载 ** 当我们查询一个对象的时候,在默认情况下,返回的只是该对象的代理对象,当用户去使用 ...

  7. Tensorflow 2.x(keras)源码详解之第十章:keras中的模型保存与加载(详解Checkpointmd5模型序列化)

      大家好,我是爱编程的喵喵.双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中.从事机器学习以及相关的前后端开发工作.曾在阿里云.科大讯飞.CCF等比赛获得多次Top名次.现 ...

  8. Hibernate懒加载

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

  9. 什么是hibernate懒加载?什么时候用懒加载?为什么要用懒加载?

    所谓懒加载(lazy)就是延时加载,延迟加载. 什么时候用懒加载呢,我只能回答要用懒加载的时候就用懒加载. 至于为什么要用懒加载呢,就是当我们要访问的数据量过大时,明显用缓存不太合适, 因为内存容量有 ...

最新文章

  1. 天龙八部3d最新服务器,天龙八部3DIOS正版服务器整合互通公告
  2. 基于 HTML5 Canvas 的交互式地铁线路图
  3. hdu2089 不要62 数位dp
  4. ITK:多相Chan和Vese稀疏场水平集分割
  5. 洛谷 P1019 单词接龙
  6. abcde依次进入一个队列_详解队列队形及口令(新教师必看)
  7. 读取csv文件 java_Java:逐步读取/流式传输CSV文件
  8. system类的 静态方法可以启动垃圾回收器。_跟小伟一起学习类加载机制
  9. python写爬虫4-多线程爬虫(采集58出租房信息)_python实现多线程爬虫
  10. vivado2021.2安装及验证教程(绝大部分适用于同软件其他版本)
  11. 天堂2芙蕾雅单机版mysql闪退_【图片】天堂2单机版-芙蕾雅。算是我这个老人对天堂2吧友的最后贡献吧!_天堂2吧_百度贴吧...
  12. 机器学习项目实战(一) 鸢尾花
  13. android 2k屏分辨率是多少,为什么大多数手机屏幕都用1080P分辨率而不用2K?
  14. javascript随机抽签程序
  15. 信息系统项目管理师学习笔记7-项目成本管理
  16. Fleet 1.9.231发布,支持window10 version 1809及以上版本,MacOs支持,但win7不支持
  17. 思维模型 DISC色彩性格
  18. postgresql扩展Geometry类型
  19. 中国无人船/无人潜航器行业前景规划与发展动向分析报告2022-2028年版
  20. 电子信息科学与技术与计算机专业相近吗,电子信息科学与技术专业简介

热门文章

  1. 标记接口,注解和注解处理器的前世今生
  2. Leet Code OJ 112. Path Sum [Difficulty: Easy]
  3. python2.7与python3的区别_Python 2.7 与Python3的区别
  4. java思考笔记——遍历Map-key的几种方法
  5. Spring容器中导入组件方式
  6. python idle退出_【ZZ】windows+python2.7在IDLE中执行sys.exit()出现的问题及解决方案
  7. 图解python_图解Python深拷贝和浅拷贝
  8. android php mysql json 查询_使用json从PHP-MySql服务器到Android获取图像
  9. verilog 给数组集体赋值_Verilog中如何对数组赋值(存储器memory详解)
  10. 冷藏温度范围_冰箱冷藏温度多少合适 冰箱冷藏温度调节范围