• Spring的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>  

     如果发现配置完以后不起作用,请看本人另外一篇博客:http://whoosh.iteye.com/admin/blogs/1154924

    Spring针对Hibernate的非JPA实现用的是OpenSessionInViewFilter,原理与这个大同小异。用了这类Filter以后会降低一定的运行效率,但是一般的web项目都会加入一些开源的缓存管理框架,这样一来,对效率的影响就变得很小了。

  • 相关阅读:
    Thymeleaf踩坑:[[ 和 ]] 被当做表达式解析,但是想要的就是数组,怎么办?
    RoamEdit 邀请码
    python:新版xlrd报 Excel xlsx file; not supported
    JavaFX学习:快捷键
    JavaFX学习:键盘事件
    JavaFX学习:连续点击事件
    JavaFX学习:Button基本使用
    (转)IDEA 更新插件时报错 SSL error probably caused by disabled SNI
    TextControl技术互助
    一个简单的Webservice的demo(中)_前端页面调用
  • 原文地址:https://www.cnblogs.com/jiligalaer/p/4095986.html
Copyright © 2020-2023  润新知