当hibernate遇上spring(OpenSessionInViewFilter)

 hibernate的延迟问题

环境strut1.x+spring+hibernate

 

Hibernate允许对关联对象、属性进行延迟加载,但是必须保证延迟加载的操作限于同一个 Hibernate Session 范围之内进行。如果 Service 层返回一个启用了延迟加载功能的领域对象给 Web 层,当Web 层访问到那些需要延迟加载的数据时,由于加载领域对象的 Hibernate Session 已经关闭,这些导致延迟加载数据的访问异常。

Spring为我们提供的OpenSessionInViewFilter过滤器为我们很好的解决了这个问题。OpenSessionInViewFilterSpring提供的一个针对Hibernate的一个支持类,其主要意思是在发起一个页面请求时打开HibernateSession,一直保持这个Session,直到这个请求结束,具体是通过一个Filter来实现的。

  由于Hibernate引入了Lazy Load特性,使得脱离HibernateSession周期的对象如果再想通过getter方法取到其关联对象的值,Hibernate会抛出一个LazyLoadException。所以为了解决这个问题,Spring引入了这个Filter,使得HibernateSession的生命周期变长。

 有两种方式可以配置实现OpenSessionInView,分别是OpenSessionInViewInterceptorOpenSessionInViewFilter,功能完全相同,只不过一个在web.xml配置,另一个在application.xml配置。

但是,使用SSH架构的项目很有可能都遇到过openSessionInView失效问题原因是因为加载spring配置文件都是通过springstruts插件来实现,即在struts的配置文件中通过ContextLoaderPlugIn在加载spring的上下文配置文件:

<plug-in

className="org.springframework.web.struts.ContextLoaderPlugIn">

<set-property property="contextConfigLocation"

value="/WEB-INF/applicationContext.xml, 

/WEB-INF/action-servlet.xml"/>

</plug-in>

通过上面的org.springframework.web.struts.ContextLoaderPlugIn作为strutsplugin来加载spring的配置文件,会绕过openSessionInView,从而使得openSessionInView失效。

因此,使用org.springframework.web.context.ContextLoaderListener来加载spring的配置文件。

解决方法:

首先:将在struts配置文件中的加载spring的配置文件(下面的代码)删掉。

<plug-in

className="org.springframework.web.struts.ContextLoaderPlugIn">

<set-property property="contextConfigLocation"

value="/WEB-INF/applicationContext.xml, 

/WEB-INF/action-servlet.xml"/>

</plug-in>

其次web.xml文件中加入

  <context-param>

    <param-name>contextConfigLocation</param-name>

        <param-value>/WEB-INF/applicationContext*.xml,classpath*:applicationContext*.xml</param-value>

  </context-param>

 

  <listener>

        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

  </listener> 

 

  <filter>

    <filter-name>hibernateFilter</filter-name>

    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>

    <init-param> 

        <param-name>singleSession</param-name> 

        <param-value>true</param-value> 

    </init-param>

  </filter>

  <filter-mapping>

    <filter-name>hibernateFilter</filter-name>

    <url-pattern>/*</url-pattern>

</filter-mapping>

即可。

PS

openSessionInView就是把session关闭延迟到view渲染以后,结合延迟加载产生作用,如果不使用延迟加载也就没有必要使用openSessionInView了。

如果使用Struts,那么需要在Struts的配置文件struts-config.xml里面配置一个SpringpluginContextLoaderPlugIn。实际上ContextLoaderListenerContextLoaderPlugIn的功能是重叠的,他们都是进行Spring配置的初 始化工作的。因此,如果你不打算使用OpenSessionInView,那么你并不需要在web.xml里面配置 ContextLoaderListener 如果需要OpenSessionInView模式,由于ContextLoaderListenerContextLoaderPlugIn功能重叠,都是初始化Spring,你不应该进行两次初始化,所以你不应该同时使用这两者,为了使得OpenSessionInView起作用,应该使用ContextLoaderListener

 

spring  有三种启用模式:

1.ContextLoaderServlet

2.ContextLoaderListener

3.ContextLoaderPlugIn

 

 

参考:http://www.javaeye.com/topic/73332

http://fusu.com.cn/post/24.html

http://www.javaeye.com/topic/15057

http://blog.csdn.net/dongyansheng_max/archive/2009/07/29/4390978.aspx

http://www.cnblogs.com/cxccbv/archive/2009/07/22/1528825.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值