spring 控制hibernate的session何时关闭.

时间:2022-06-15 19:04:14

 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.