hibernate下著名的延迟加载问题和1:N问题 zz

问题描述:
如果延迟的操作是发生在CRUD的操作所在的session关闭之后,就会出现这个异常.

什么是延迟的操作?
1.fetch = "LAZY" 机制
ManyToOne,OneToMany,ManyToMany中对关联对象的延迟调用
读出持久化对象时,并不把关联的对象实际读出,而是延迟到访问到持久化对象的关联对象属性时,才向数据库发成读操作
2.load()方法
获取持久化对象的load()方法,并不把对象实际读出,而是延迟到 访问到持久化对象时,才向数据库发成读操作


load() 与 fetch=LAZY 机制有什么不同?
1.首先,二者很象,都是延迟调用,都会报LazyInitializationExcept2. load()是比fetch=LAZY 更lazy 因为fetch=LAZY是延迟调用关联对象入内存缓存
load()是延迟整个持久化对象,等于什么都没读入内存缓存


实验场景下的LazyInitializationException:no session or session was closed
Session session1 = sf.getCurrentSession();
Transaction tran1 = session1.beginTransaction();
Group_3 group = (Group_3) session1.get(Group_3.class, 6);
tran1.commit(); // 问题出在此语句,LAZY 前后两次发sql字串,跨了session
for(User_3 user:group.getUsers())
System.out.println(user.getId()+":"+user.getName());
22:48:23,187 ERROR LazyInitializationException:42 - failed to lazily initialize a collection of role: com.machome.one2many_many2one_bi.Group_3.users, no session or session was closed


实际应用中的LazyInitializationException:no session or session was closed
servlet或action类:
List<xxx> xxxs = findAll(); // 此方法结束时,session就关闭了
request.setAttribute("xxxs",xxxs);

JSP页面:
显示request.getAttribute("xxxs");
22:48:23,187 ERROR LazyInitializationException:42 - failed to lazily initialize a collection of role: com.machome.one2many_many2one_bi.Group_3.users, no session or session was closed


延迟加载异常的解决
1.简单的解决办法---关闭LAZY机制
@ManyToOne(fetch=FetchType.EAGER)
hibernate多对一,Many端缺省就是EAGER机制,One端缺省是LAZY
优点:
简单,实现容易

缺陷:
1.fetch是ManyToOne,OneToMany,ManyToMany的机制,所以关闭它只能解决ManyToOne等的延迟加载异常,但无法解决load()方法的延迟加载异常

2.因为这等于是关闭延迟加载,所以无法享受延迟加载带来的对性能方面的益处

3.对ManyToOne,OneToMany双向的情况,两边都设FETCH=EAGER,有可能出现死锁的情况
2.更合理的解决办法---用spring的OpenSessionInViewFilter把session的周期交给servlet filter来管理
每当有request进来,就打开一个session,response结束之后才关闭它,这样可以让session存在于整个servlet request请求周期中
采用spring的OpenSessionInView模式

web.xml下加入:
<!-- ##################### 解决Lazy Initial Exception问题 ###########-->
<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>*.do</url-pattern>
</filter-mapping>

<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>*.jsp</url-pattern>
</filter-mapping>
优点:
1.既能解决多对一得FETCH=LAZY问题,也能解决load()方法的问题
2.同时能允许用户使用FETCH=LAZY机制和load()方法,享受其带来的对性能的提升.

缺陷:
1.需要整合hibernate入spring
2.仅支持java web环境,对java application 环境不支持


和hibernate一样秉承OrMapping Persistence理论的JPA下也有延迟加载异常
下面是spring 针对JPA的servlet过滤器
web.xml下加入:
<filter>
<filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
<filter-class>
org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>SpringOpenEntityManagerInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>


所谓的1+N问题-----其实就是多对一一对多fetch=EAGER机制带来的对性能的损耗
每次获取持久化对象,都会同时调入关联对象,hibernate会发出多条select语句,很耗资源
解决方法:
1。fetch=LAZY 最常用
2. BatchSize
设@BatchSize,这样hibernate自动把N条组成一条或几条
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值