<span style="font-size:18px;"><!-- Open Entity Manager in View filter--> <filter> <filter-name>openEntityManagerInViewFilter</filter-name> <filter-cla
<span style="font-size:18px;"><!-- Open Entity Manager in View filter-->
- <filter>
- <filter-name>openEntityManagerInViewFilter</filter-name>
- <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
- </filter>
- <filter-mapping>
- <filter-name>openEntityManagerInViewFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping></span>
在Java Web項目中使用Hibernate經常會遇到LazyInitializationException。這是因為controller和model層(java代碼)將通過JPA的一些啟用了延遲載入功能的領域(如用getRefrence()方法或者在關聯關係中採用fetch=FetchType.LAZY)返回給view層(jsp代碼)的時候,由於載入領域對象的JPA Session已經關閉,導致這些延遲載入的數據訪問異常。
這時就可以使用OpenEntityManagerInViewFilter來將一個JPAsession與一次完整的請求過程對應的線程相綁定。請看一段偽代碼:
- Service{
- entitymanager=context.getEntityManager();
- if(entitymanager==null) context.put(factory,createEntityManager());
- entitymangager=context.getEntityManager();
- entitymanager.begin();
- public void find(Integer productid){//除了這個方法外,其他都是通過AOP織入的
- em.getReference(Product.class,productid));
- }
- entitymanager=context.getEntityManager();
- entitymanager.commit();
- entitymanager.close();
- }
上面的偽代碼演示瞭如果我們想調用我們自己定義的一個find()方法,spring會在該方法的前後織入一些代碼來開始事物和關閉session。當view層調要用這個find()方法獲取的對象(由於採用了延遲載入模式,只有到要使用到該對象的時候才會讓session去資料庫取)的時候,實際上session已經關閉了,不能再讓session獲取對象。
OpenEntityManagerInViewFilter會讓session一直到view層調用結束後才關閉,請看下麵的偽代碼:
[html] view plain copy- Filter{
- doFilter(chain){
- context.getEntityManager().open();
- chain.doFilter(req,res){
- xxxAction{
- execute(){
- Product product=service.find(productid);//此時該對象為游離狀態,實際上並沒有在資料庫獲得值。
- req.setAttibute("Product",produxt);//這時候才到資料庫裡面去取值
- return mapping.findForward("product");
- }
- }
- }
- context.getEntityManager().close()...
- }
- }
如果沒使用OpenEntityManagerInViewFilter,session會在service.find()方法後就被關閉,用了以後session在整個view層結束後才關閉。
摘自:http://whoosh.iteye.com/blog/1300721