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项目都会加入一些开源的缓存管理框架,这样一来,对效率的影响就变得很小了。

时间: 2024-10-12 22:06:13

Spring的OpenEntityManagerInViewFilter的相关文章

spring 4 + jpa(hibernate 3/4) + spring mvc 多数据源配置

先从persistence.xml开始: <?xml version=”1.0″ encoding=”UTF-8″?><persistence version=”2.1″ xmlns=”http://java.sun.com/xml/ns/persistence” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” xsi:schemaLocation=”http://java.sun.com/xml/ns/persistence

struts2+hibernate-jpa+Spring+maven 整合(2)

之前的一篇已经讲到了 spring 与struts2 的整合, 其实对于struts2+hibernate-jpa+Spring 之间的整合的文章已经相当多了, 也相当成熟了,只要不是各自的版本不兼容之外,其他的几乎没啥问题, 不行mybatis那样是不是的冒点让人头疼的事情来 下面修改pom.xml ,把hibernate 的jar 关联进来; <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="

快速搭建springmvc+spring data jpa工程

一.前言 这里简单讲述一下如何快速使用springmvc和spring data jpa搭建后台开发工程,并提供了一个简单的demo作为参考. 二.创建maven工程 http://www.cnblogs.com/hujunzheng/p/5450255.html 三.配置文件说明 1.application.properties jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/springdata?u

spring mvc 的jpa JpaRepository数据层 访问方式汇总

spring mvc 的jpa JpaRepository数据层 访问方式汇总 博客分类: spring jpa springjpaJpaRepository 本文转载至:http://perfy315.iteye.com/blog/1460226 AppleFramework在数据访问控制层采用了Spring Data作为这一层的解决方案,下面就对Spring Data相关知识作一个较为详细的描述. 1.Spring Data所解决的问题 Spring Data :提供了一整套数据访问层(DA

Hibernate + Spring (quartz) 整合懒(延迟)加载问题

开发项目的时候 在一个Job中执行了数据库操作, 用的是懒加载,但是如下错误 org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: ......., no session or session was closed 项目中使用 hibernate 注解的方式配置懒加载, 不是xml配置文件, 下面列出从网上搜集到的解决方案 1, 报如下错误 org.hibernat

spring完整demo实例

我前几篇分散的说了spring mvc,这一篇我完整的说一下,仅供参考,如果大家要用, 只需要改下路径就行,可能比较长,大家耐心看哦.我会在最后把工程连接贴上. 先贴hibernate的连接配置:hibernate.properties dataSource.url=jdbc\:mysql\://127.0.0.1\:3306/dorm dataSource.password=123456 dataSource.username=root dataSource.driverClassName=c

springMVC+spring+JPA配置文件

web.xml <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://

spring data jpa使用懒操作

如果model对象的某属性使用lazy load,调用这个属性时会报错, failed to lazily initialize a collection of role could not initialize proxy - no Session 查了一圈,得到两个方案 a)     放弃懒操作,改lazy为eager 可是,如果我只需要一个姓名,却把人的家谱都翻出来了,很浪费很无效啊. b)     使用OpenSessionInViewFilter 配置的时候,发现不能用,因为他需要se

Spring MVC 的 研发之路 (二)

二.web.xml的简单配置介绍1 1.启动Web项目时,容器回去读web.xml配置文件里的两个节点<context-param>和<listener> 2.接着容器会创建一个servletContext(上下文)应用范围内都能使用这个上下文 3.接着容器会将读取到<context-param>转化为键值对,并交给ServletContext. 4.通过<listener>创建监听 5.在监听的类中会有一个contextInitialized(Servle