http://blog.csdn.net/dengyin2000/article/details/448341
在用spring管理hierbernate的事务我们一般都用TransactionProxyFactoryBean去配置我们的Service方法.
如.
<bean id="baseTxProxy" lazy-init="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="is*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<!-- <bean id="userManager" parent="baseTxProxy">
<property name="target">
<bean class="com.javaeye.user.impl.hibernate.UserManagerImpl" autowire="byName">
<property name="cacheQueries"><value>true</value></property>
</bean>
</property>
</bean>
-->
<bean id="userService" parent="baseTxProxy">
<property name="target">
<bean class="com.dengyin.report.service.impl.UserServiceImpl" autowire="byName"/>
</property>
</bean>
<bean id="dailyReportService" parent="baseTxProxy">
<property name="target">
<bean class="com.dengyin.report.service.impl.DailyReportServiceImpl" autowire="byName"/>
</property>
</bean>
我们可以想得到TransactionProxyFactoryBean是使用aop在Service方法之前open 一个session, begin Trans.在Service结束之后Commit Trans, close session.
note:如果一个service中调用另外一个service,如果另外一个service的事务传播类型是required的话,那么两个service中使用的是同一个session
但是我们使用spring的OpenSessionInViewFilter的时候就不能在Service方法后close session了. 应该是在Render page之后再关闭session的.所以我跟踪了spring的代码. 最后发现了spring是怎样做的(跟了好久,主要是上班偷偷摸摸搞的).
HibernateTransactionObject txObject = (HibernateTransactionObject) transaction;
if (txObject.getSessionHolder() == null) {
Interceptor entityInterceptor = getEntityInterceptor();
Session newSession = (entityInterceptor != null ?
getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession());
if (logger.isDebugEnabled()) {
logger.debug("Opened new Session [" + newSession + "] for Hibernate transaction");
}
txObject.setSessionHolder(new SessionHolder(newSession), true);
}
txObject.getSessionHolder().setSynchronizedWithTransaction(true);
session = txObject.getSessionHolder().getSession();
这段代码是在进行Service之前的. 如果当前thread没有session的话就执行txObject.setSessionHolder(new SessionHolder(newSession), true);注意这里set了一个true值. 我们来看看txObject是一个什么东西.
private static class HibernateTransactionObject extends JdbcTransactionObjectSupport {
private SessionHolder sessionHolder;
private boolean newSessionHolder;
public void setSessionHolder(SessionHolder sessionHolder, boolean newSessionHolder) {
this.sessionHolder = sessionHolder;
this.newSessionHolder = newSessionHolder;
}
public SessionHolder getSessionHolder() {
return sessionHolder;
}
public boolean isNewSessionHolder() {
return newSessionHolder;
}
public boolean hasTransaction() {
return (this.sessionHolder != null && this.sessionHolder.getTransaction() != null);
}
public void setRollbackOnly() {
getSessionHolder().setRollbackOnly();
if (getConnectionHolder() != null) {
getConnectionHolder().setRollbackOnly();
}
}
public boolean isRollbackOnly() {
return getSessionHolder().isRollbackOnly() ||
(getConnectionHolder() != null && getConnectionHolder().isRollbackOnly());
}
}
我们看看Service方法之后spring怎样close session的.
Session session = txObject.getSessionHolder().getSession();
if (txObject.isNewSessionHolder()) {
if (logger.isDebugEnabled()) {
logger.debug("Closing Hibernate Session [" + session + "] after transaction");
}
SessionFactoryUtils.releaseSession(session, getSessionFactory());
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Not closing pre-bound Hibernate Session [" + session + "] after transaction");
}
if (txObject.getSessionHolder().getPreviousFlushMode() != null) {
session.setFlushMode(txObject.getSessionHolder().getPreviousFlushMode());
}
}
txObject.getSessionHolder().clear();
当txObject.isNewSessionHolder()的时候才会close session.
总结:
所以当Service方法之间没有存在的session时spring会开一session,然后结束的时候close session.
当Service方法之间有存在的session的话,Service方法结束时并没有关闭 session.