hibernate的 open session in view

来源:互联网 发布:网络彩票违法吗 编辑:程序博客网 时间:2024/05/17 05:12

http://fuliang.iteye.com/blog/146965


我们在使用Hibernate的lazy load来优化性能的时候,只要Session关闭后再试图访问未被载入的对象时,就会出现异常。通常使用在事务之内来访问数据是适合的,但是有时候我们需要强制载入这些数据,例如在Web视图中访问这些模型对象。

    在业务层强制载入这些数据,通常不是很好的解决方案,因为不同的视图在使用业务方法的时候,需要的数据通常不一样,这样业务方法可能绑定到特定的控制器中。
    在业务层上面增加一个Facade层来解决这个问题,同样也会增加一层不太必要的封装,增加了复杂性,POJO in Action一书中的例子就是这么设计的(POJO in Action感觉是本蛮不错的书),详细的可以看看这本书。
    通常Open Session in View模式相对来说是个不错的解决方案。事务在服务层结束,但关联的Hibernate Session保持打开状态,直到视图生成完成为止。这样及早的释放了数据库锁和连接,并且视图中可以通过lazy load来加载。
    Spring支持这种即开即用的模式,通过org.springframework.orm.hibernate.support.OpenSessionInViewFilter(可以和任何web层技术一起使用)或者OpenSessionInViewInterceptor(和Spring的Web MVC框架一起使用)。
Spring的这两种实现,他们支持两种操作方式:单一会话模式和延迟关闭模式
1、单一会话模式:
通过在请求范围的Session上来操作事务,单个Hibernate Session将用于整个HTTP请求。默认情况下是单一会话方式,它是Open Session in View比较有效的版本。请求范围内的Hibernate Session视为第一级缓存,整个请求内只载入每个持久性对象一次。主要的缺点是:所有的Session管理的对象都必须是唯一的,这样视图从HttpSession中重新attach一个对象,可能导致Hibernate重复对象的异常。
2、延迟关闭方式:
每个事务将和平常一样使用其自身的Session,但这些Session中的每一个都在事务完成后保持开启,在视图生成后关闭。这样可以通过使用新的Hibernate Session来避免重复对象的问题,所有Session都在事务完成后保持开启,在他们每个上允许lazy load。但是,如果单个持久性对象涉及到多个事务,可能导致问题。Hibernate需要一个持久化对象与一个Hibernate Session关联,而不是同时与多个。这种情况下应该使用单一会话模式。

在web.xml中配置:


    <filter>        <filter-name>OpenSessionInView</filter-name>        <filter-class>org.springframework.orm.hibernate.support.OpenSessionInVewFilter</filter-class>      <!--如果使用延迟关闭方式        <init-param>          <param-name>singleSession</param-name>          <param-value>false</param-value>        </init-param>      -->      </filter>            <filter-mapping>        <filter-name>OpenSessionInView</filter-name>        <url-pattern>*.do</url-pattern><!--以.do结束的的url为例-->      </filter-mapping>  

Spring Web MVC OpenSessionInViewInterceptor的配置:


    <bean id="openSessionInView" class="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor">       <property name="sessionFactory">         <ref bean="sessionFactory">       </property>      <!--如果使用延迟关闭方式       <property name="singleSession">         <value>false</value>       </property>      -->      </bean>            <bean id="myUrlMapping" class="org.springframeword.web.servlet.handler.SimpleUrlHandlerMapping">        <property name="interceptors">          <list>            <ref bean="openSessionInView">          </list>        </property>        <property name="urlMap">          <!-- url mappings-->        </property>      </bean>  



原创粉丝点击