org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:

转载自:https://blog.csdn.net/lch_2016/article/details/81051685

什么是hibernate懒加载?什么时候用懒加载?为什么要用懒加载?懒加载解决方法

转自:https://www.cnblogs.com/cornucopia/articles/4541621.html

转自:https://blog.csdn.net/qq_21033663/article/details/51236009

总结:

所谓懒加载(lazy)就是延时加载,延迟加载。
什么时候用懒加载呢,我只能回答要用懒加载的时候就用懒加载。
至于为什么要用懒加载呢,就是当我们要访问的数据量过大时,明显用缓存不太合适,
因为内存容量有限 ,为了减少并发量,减少系统资源的消耗,

我们让数据在需要的时候才进行加载,这时我们就用到了懒加载

lazy有三个属性:true、false、extra
【true】:默认取值,它的意思是只有在调用这个集合获取里面的元素对象时,才发出查询语句,加载其 
     集合元素的数据 
【false】:取消懒加载特性,即在加载对象的同时,就发出第二条查询语句加载其关联集合的数据 

【extra】:一种比较聪明的懒加载策略,即调用集合的size/contains等方法的时候,hibernate并不会去加载整个集合的数据,而是发出一条聪明的SQL语句,以便获得需要的值,只有在真正需要用到这些集合元素对象数据的时候,才去发出查询语句加载所有对象的数据。

解决方案:

1)不使用懒加载:将子表配置文件中lazy属性改为false,对某一个级联关系不使用懒加载
 2)使用过滤器,把close Session这一步推迟到得到页面结果后执行。这里可以采用spring中OpenSessionInViewFilter(这是一个过滤器)来实现。这个方法是将session交给servlet filter管理,每当一个请求来之后就会开启一个session,只有当响应结束后才会关闭。
 3)手动将需要的子表数据从数据库缓存加载到jvm内存中。例如Classroom与Student实体类存在一对多关系(多对多同样适用)

原文:

 所谓懒加载(lazy)就是延时加载,延迟加载。当两个及以上表使用hibernate来管理级联关系时,一个表被加载到jvm内存时,其相关表可以暂存在数据库的缓存中,当需要使用相关表数据时在加载到jvm内存中,通过懒加载机制可以减少内存中不必要的开销,以提高程序的性能。

    需要注意的是,当使用懒加载时,如果将session关闭,则断开了与数据库的连接,此时如果要访问子表数据,由于子表数据是存放在数据库的缓存中,而连接已经关闭,则访问子表数据会抛出LazyInitializationException异常。

     解决方法:

    1)不使用懒加载:将子表配置文件中lazy属性改为false,对某一个级联关系不使用懒加载

     <many-to-one name="parent" class="ParrentClass" column="parentId" lazy="false"></many-to-one>  

    注:对于many-to-many同样适用

    或者将整个子表设置为对任何父表都不使用懒加载,则对整个子表都不使用懒加载

    <class name="ChildClass" table="childTable" lazy="false">

    2)使用过滤器,把close Session这一步推迟到得到页面结果后执行。这里可以采用spring中OpenSessionInViewFilter(这是一个过滤器)来实现。

    在web.xml中加入配置

    <filter>  
       <filter-name>OpenSessionInViewFilter</filter-name>  
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>  
    </filter>  
    <filter-mapping>  
       <filter-name>OpenSessionInViewFilter</filter-name>  
       <url-pattern>*.action</url-pattern>  
    </filter-mapping>  

    3)手动将需要的子表数据从数据库缓存加载到jvm内存中。例如Classroom与Student实体类存在一对多关系(多对多同样适用),即

public Classroom {

    private Set<Student> students;

    .........

}

dao层有

List<ClassRoom> list = session获得结果集操作

for (Classroom classroom : list)  {
    Hibernate.initialize(classroom.getStudents()); //循环将classroom实体对应的Student集合patch到jvm内存中

}

session.close();

方法比较:第一种方法简单粗暴,优点是不必太在意延迟加载异常,因为不会发生,缺点是每次都将所有相关数据加载到jvm内存中,消耗内存资源;第二种方法是javaweb中常用的方法,优点是根据需要合理确定加载时间以及是否加载,缺点是只能用在J2EE中,对于J2SE项目则不适用;第三种方法,优点是灵活掌控何时加载,缺点是增加额外代码,并且需要加载子表数据但是忘记在session关闭前将其拉入jvm内存中时,会抛出LazyInitializationException

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值