web.xml中openEntityManagerInViewFilter的作用

  在Java Web項目中使用Hibernate經常會遇到LazyInitializationException 。這是因爲controller和model層(java代碼)將通過JPA的一些啓用了延遲加載功能 的領域(如用getRefrence() 方法或者在關聯關係中採用fetch=FetchType.LAZY )返回給view層(jsp代碼)的時候,由於加載領域對象的JPA Session已經關閉,導致這些延遲加載的數據訪問異常。

這時就可以使用OpenEntityManagerInViewFilter來將一個JPAsession與一次完整的請求過程對應的線程相綁定。請看一段僞代碼:

Java代碼 
  1. Service{  
  2.         entitymanager=context.getEntityManager();  
  3.         if(entitymanager==null) context.put(factory,createEntityManager());  
  4.         entitymangager=context.getEntityManager();  
  5.         entitymanager.begin();  
  6.         public void find(Integer productid){//除了這個方法外,其他都是通過AOP織入的  
  7.             em.getReference(Product.class,productid));  
  8.         }  
  9.         entitymanager=context.getEntityManager();  
  10.         entitymanager.commit();  
  11.         entitymanager.close();  
  12. }  

 上面的僞代碼演示瞭如果我們想調用我們自己定義的一個find()方法,spring會在該方法的前後織入一些代碼來開始事物和關閉session。當view層調要用這個find()方法獲取的對象(由於採用了延遲加載模式,只有到要使用到該對象的時候纔會讓session去數據庫取)的時候,實際上session已經關閉了,不能再讓session獲取對象。

OpenEntityManagerInViewFilter會讓session一直到view層調用結束後才關閉,請看下面的僞代碼:

Java代碼  收藏代碼
  1. Filter{  
  2.         doFilter(chain){  
  3.             context.getEntityManager().open();  
  4.             chain.doFilter(req,res){  
  5.                 xxxAction{  
  6.                     execute(){  
  7.                         Product product=service.find(productid);//此時該對象爲遊離狀態,實際上並沒有在數據庫獲得值。  
  8.                         req.setAttibute("Product",produxt);//這時候纔到數據庫裏面去取值  
  9.                         return mapping.findForward("product");  
  10.                     }  
  11.                 }  
  12.             }  
  13.             context.getEntityManager().close()...  
  14.         }  
  15.     }  

 如果沒使用OpenEntityManagerInViewFilter,session會在service.find()方法後就被關閉,用了以後session在整個view層結束後才關閉。

配置該filter的方法:在web.xml文件中加入如下代碼

Xml代碼 
  1. <filter>  
  2.         <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>  
  3.         <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>  
  4.         <init-param>  
  5.         <!-- 指定org.springframework.orm.jpa.LocalEntityManagerFactoryBean在spring配置文件中的名稱,默認值爲entityManagerFactory  
  6.         如果LocalEntityManagerFactoryBean在spring中的名稱不是entityManagerFactory,該參數一定要指定,否則會出現找不到entityManagerFactory的例外 -->  
  7.             <param-name>entityManagerFactoryBeanName</param-name>  
  8.             <param-value>entityManagerFactory</param-value>  
  9.         </init-param>   
  10.     </filter>  
  11.     <filter-mapping>  
  12.         <filter-name>Spring OpenEntityManagerInViewFilter</filter-name>  
  13.         <url-pattern>/*</url-pattern>  
  14.     </filter-mapping>  
  Spring針對Hibernate的非JPA實現用的是OpenSessionInViewFilter,原理與這個大同小異。用了這類Filter以後會降低一定的運行效率,但是一般的web項目都會加入一些開源的緩存管理框架,這樣一來,對效率的影響就變得很小了。
轉載自:http://whoosh.iteye.com/blog/1300721
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章