hibernate 延迟加载和立即加载

55 篇文章 0 订阅

懒加载

懒加载FatchType.LAZY也称为延迟加载,是Hibernate3关联关系对象默认的加载方式,所谓懒加载就是当在真正需要数据的时候,才真正执行数据加载操作。简单理解为,只有在使用的时候,才会发出sql语句进行查询。

我们使用Session的load()方法加载数据或者一对多关联映射在使用延迟加载的情况下从一的一方加载多的一方,得到的都是虚拟代理,简单的说返回给用户的并不是实体本身,而是实体对象的代理。代理对象在用户调用getter方法时才会去数据库加载数据。

懒加载的有效期是在session打开的情况下。当session关闭后,会报异常 no Session。当调用load方法加载对象时,返回代理对象,等到真正用到对象的内容时才发出sql语句。获取持久状态对象之后,还需要获取关联对象,此时才会真正发出sql,获取值

好处:提高性能,但是如果把entityManager 提前关闭,会出现(延迟加载)延迟初始化异常org.hibernate.LazyInitializationException: could not initialize proxy - no Session

//懒加载只会查询要查询的表不会查询关联表
Hibernate: select product0_.id as id1_2_0_, product0_.dir_id as dir_id3_2_0_, product0_.name as name2_2_0_ from t_product product0_ where product0_.id=?
cn.itsource.jpa.Product@75f65e45

一对多(通过一个查多个)、多对多:通常情况下我们都是采用延迟加载
多对一(通过多个查一个)、一对一:通常情况下我们都采用立即加载

立即加载

急加载FatchType.EAGER 也称为立即加载,是立即执行sql语句。
急切加载 发送sql的时候,会产生左外连接查询数据。
在session没有关闭之前,如果访问除id外的其他属性才会发sql语句去查询,我们经常犯的一个错误就是在当前session关闭以后访问由load()加载的对象的非id属性,
此时Hibernate尝试通过当前session发sql查询,但发现session已经关闭,这样就会发出no session的异常 。

//急切加载 查询产品会把产品类型也查询出来 发送sql的时候,会产生左外连接查询数据。
Hibernate: select product0_.id as id1_2_0_, product0_.dir_id as dir_id3_2_0_, product0_.name as name2_2_0_, productdir1_.id as id1_3_1_, productdir1_.name as name2_3_1_ from t_product product0_ left outer join t_productDir productdir1_ on product0_.dir_id=productdir1_.id where product0_.id=?
cn.itsource.jpa.Product@62f4ff3b

为什么要用延迟加载

使用延迟加载的目的是为了减少系统资源的消耗,当我们要访问的数据量过大时,明显用缓存不太合适,因为内存容量有限 ,为了减少并发量,减少系统资源的消耗,我们让数据在需要的时候才进行加载,这时我们就用到了懒加载。

例如查询课程和选择此课程的学生的时候,当一个课程中只有几十个学生的时候,我们使用延迟加载和立即加载对系统资源的消耗并不明显,但是当一个课程有几千万个学生的时候,同时我们并不是立刻使用所有学生的信息。我们如果使用立即加载就会造成大量浪费系统资源,此时使用延迟加载的随用随取模式就会有很大的优势

假如在student对象中包含一个head对象
如果你确定在用student对象的时候就要用到head对象里的属性,那你就设置立即加载,因为设置立即加载那么在查询student的同时就会查询student的head,hibernate就会在查询的时候关联两张表从而生成的sql就可能只有一条。而如果你设置的是延迟加载,那么肯定会要生成1+N条sql语句:其中“1”是查询student的语句,“N”是根据N个student的id去查询head的N条语句。而且,延迟加载是要用到的时候才去执行查询,这样系统判断哪里需要加载,哪里不需要加载也需要时间,性能上肯定就不如立即加载了!
如果,你是有的地方需要用到student的时候才用到head属性,那么你就设置成延迟加载,因为查询2张表的数据肯定要比查询1张表的数据消耗大。
到底要怎样设置就要看你的实际需求了

延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。

延迟加载与session关闭的矛盾一般可以这样处理

  1. 关闭延迟加载特性。这种方式操作起来比较简单,因为Hibernate的延迟加载特性是可以通过映射文件或者注解进行配置的,但这种解决方案存在明显的缺陷。首先,出现"no session or session was closed"通常说明系统中已经存在主外键关联,如果去掉延迟加载的话,每次查询的开销都会变得很大。
  2. 在session关闭之前先获取需要查询的数据,可以使用工具方法Hibernate.isInitialized()判断对象是否被加载,如果没有被加载则可以使用Hibernate.initialize()方法加载对象。
  3. 使用拦截器或过滤器延长Session的生命周期直到视图获得数据。Spring整合Hibernate提供的OpenSessionInViewFilter和OpenSessionInViewInterceptor就是这种做法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值