我们在使用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-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 >
OpenSessionInViewInterceptor的配置Spring Web MVC:
< 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 >