downpour 写的OpenSessionInView详解
http://www.iteye.com/topic/32001?page=1
SpringSide团队日志
http://calvin.blog.javascud.org/post/46.htm
HibernateTemplate中HibernateCallback的事务
http://www.blogjava.net/caixuetao/articles/113433.html
open session and Hibernate事务处理机制
http://blog.csdn.net/Explorering/archive/2006/06/14/797399.aspx
Hibernate事务
http://www.yesky.com/imagesnew/software/spring/orm.html
看完以上文章,对OpensessionInView有了更深的理解.
它为了实现Hibernate的延迟加载功能。基于一个请求一个hibernate session的原则。
spring中对OpenSessionInViewFilter的描述如下:
它是一个Servlet2.3过滤器,用来把一个Hibernate Session和一次完整的请求过程对应的线程相绑定。目的是为了实现"Open Session in View"的模式。
例如: 它允许在事务提交之后延迟加载显示所需要的对象。
一.如果配置OpensessionInView
1)request请求,服务器开个线程响应客户端
2)OpenSessionInViewFilter打开Session) ,绑定到当前线程
3) ServletDispatcher -> Action
4)打开Connection,启动事务) -> spring bean -> another spring bean -> (提交事务) -> bean执行完毕,
5)返回Action
6)render view(JSP/Template)
7)(OpenSessionInViewFilter关闭Session和Connection,取消绑定
其中第四步,在bean的dao里调用某方法时,继承的HibernateDaoSupport类,它的的HibernateTemplete的session也是判断当前线程有无session,若有的话直接使用.
对于Spring的OpenSessionInViewFilter来说,虽然数据库连接被保持了过长的时间,但是并没有锁定数据库资源,特别是事务资源。因为Spring的事务是通过TransactionInterceptor来实现的,在MVC结构中,当最后一个业务bean被调用结束以后,Transaction就已经被提交了。此后,虽然数据库连接还保持中,但是数据库资源没有锁定问题。
二.如果没用OpensessionInView
如果没有配置OpensessionInView,HibernateTemplete里的方法每次都是新开一个session,执行完关闭session
假设在你的应用中Hibernate是通过spring 来管理它的session.而且在你的应用中没有使用OpenSessionInViewFilter或者OpenSessionInViewInterceptor。session会在transaction结束后关闭。
如果你采用了spring的声明式事务模式,它会对你的被代理对象的每一个方法进行事务包装(AOP的方式)。如下:
<bean id="txProxyTemplate" abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean id="manager" parent="txProxyTemplate">
<property name="target">
<bean class="org.appfuse.service.impl.BaseManager">
<property name="dao" ref="dao"/>
</bean>
</property>
</bean>
spring默认对RunTimeException及其子类回滚(例如DAOAccessException),也可以通过配置对任何CheckedException回滚
目标类org.appfuse.service.impl.BaseManager 的 save *方法的事务类型PROPAGATION_REQUIRED ,remove* 方法的事务类型PROPAGATION_REQUIRED,其他的方法的事务类型是PROPAGATION_REQUIRED,readOnly。
所以调用这个名为“manager”的bean的方法之后session就关掉了.
关于事务:
在业务层用AOP的方式通过TransactionInterceptor进行了事务的begin和commit的拦截,而在两个方法之间,你的transactionStatus一直与Thread绑定,在事务声明为required的时候DAO的方法都会参与到这个事务中,就是说这是同一个事务