問題描述:

  如果延遲的操作是發生在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.028keji.com/software/741.html
2017年7月10日
作者:雞啄米 分類:軟件開發 瀏覽: 評論:0