问题描述:

  如果延迟的操作是发生在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下加入:

XML/HTML代码
  1.    <!-- ##################### 解决Lazy Initial Exception问题 ###########-->  
  2.    <filter>  
  3.            <filter-name>OpenSessionInViewFilter</filter-name>  
  4.            <filter-class>  
  5. org.springframework.orm.hibernate3.support.OpenSessionInViewFilter   
  6.            </filter-class>  
  7.    </filter>  
  8.    <filter-mapping>  
  9.        <filter-name>OpenSessionInViewFilter</filter-name>  
  10.         <url-pattern>*.do</url-pattern>  
  11.    </filter-mapping>  
  12.     
  13.    <filter-mapping>  
  14.        <filter-name>OpenSessionInViewFilter</filter-name>  
  15.         <url-pattern>*.jsp</url-pattern>  
  16.    </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下加入:

XML/HTML代码
  1. <filter>   
  2.    <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>   
  3.    <filter-class>  
  4. org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter  
  5. </filter-class>                                          
  6. </filter>   
  7. <filter-mapping>   
  8.    <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>   
  9.    <url-pattern>*.action</url-pattern>   
  10. </filter-mapping>  

  所谓的1+N问题-----其实就是多对一一对多fetch=EAGER机制带来的对性能的损耗

  每次获取持久化对象,都会同时调入关联对象,hibernate会发出多条select语句,很耗资源

  解决方法:

  1。fetch=LAZY   最常用

  2. BatchSize

  设@BatchSize,这样hibernate自动把N条组成一条或几条

除非特别注明,鸡啄米文章均为原创
转载请标明本文地址:http://www.jizhuomi.com/software/741.html
2017年7月10日
作者:鸡啄米 分类:软件开发 浏览: 评论:0