org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:
转载自//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
for (Classroom classroom : list) {
Hibernate.initialize(classroom.getStudents()); //循环将classroom实体对应的Student集合patch到jvm内存中
}
session.close();
方法比较:第一种方法简单粗暴,优点是不必太在意延迟加载异常,因为不会发生,缺点是每次都将所有相关数据加载到jvm内存中,消耗内存资源;第二种方法是javaweb中常用的方法,优点是根据需要合理确定加载时间以及是否加载,缺点是只能用在J2EE中,对于J2SE项目则不适用;第三种方法,优点是灵活掌控何时加载,缺点是增加额外代码,并且需要加载子表数据但是忘记在session关闭前将其拉入jvm内存中时,会抛出LazyInitializationException
还没有评论,来说两句吧...