HibernateDaoSupport Session关闭不了,连接数过多。

getSession()这个方法本身其实返回的是与当前事务绑定的Session对象,在HibernateDaoSupport中使 用,HibernateDaoSupport本身是不负责对这个Session对象进行关闭的,所以在其中有一个对应的releaseSession() 方法,用于关闭Session。

但是一般使用Spring时,我们会采用HibernateTransactionManager进行事务管理,把事务配置在Service层。 此时,它会帮助我们关闭与当前事务绑定的Session对象,这个可以参照HibernateTransactionManager类中的 doCleanupAfterCompletion方法,它是一个抽象方法的实现。再追溯上去,会发现,在事务commit或者rollback的时候, 会有一段finally代码,专门调用执行该方法的代码:

Java代码
  1. finally  {  
  2.             cleanupAfterCompletion(status);  
  3.         }  
  4.   
  5.     private   void  cleanupAfterCompletion(DefaultTransactionStatus status) {  
  6.         status.setCompleted();  
  7.         if  (status.isNewSynchronization()) {  
  8.             TransactionSynchronizationManager.clearSynchronization();  
  9.             TransactionSynchronizationManager.setCurrentTransactionName(null );  
  10.             TransactionSynchronizationManager.setCurrentTransactionReadOnly(false );  
  11.             if  (status.isNewTransaction()) {  
  12.                 TransactionSynchronizationManager.setActualTransactionActive(false );  
  13.             }  
  14.         }  
  15.         if  (status.isNewTransaction()) {  
  16.             doCleanupAfterCompletion(status.getTransaction());  
  17.         }  
  18.         if  (status.getSuspendedResources() !=  null ) {  
  19.             if  (status.isDebug()) {  
  20.                 logger.debug("Resuming suspended transaction" );  
  21.             }  
  22.             resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources());  
  23.         }  
  24.     }  
finally {
			cleanupAfterCompletion(status);
		}

	private void cleanupAfterCompletion(DefaultTransactionStatus status) {
		status.setCompleted();
		if (status.isNewSynchronization()) {
			TransactionSynchronizationManager.clearSynchronization();
			TransactionSynchronizationManager.setCurrentTransactionName(null);
			TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
			if (status.isNewTransaction()) {
				TransactionSynchronizationManager.setActualTransactionActive(false);
			}
		}
		if (status.isNewTransaction()) {
			doCleanupAfterCompletion(status.getTransaction());
		}
		if (status.getSuspendedResources() != null) {
			if (status.isDebug()) {
				logger.debug("Resuming suspended transaction");
			}
			resume(status.getTransaction(), (SuspendedResourcesHolder) status.getSuspendedResources());
		}
	}



故而,只要参与了事务,HibernateTransactionManager会帮你正确关闭Session。

不过很多的web应用都会采用OpenSessionInView模式,也就是Session会被保持到View层。同样经过 HibernateTransactionManager,为什么使用了OpenSessionInView模式以后,Session就不会被关闭呢?这 是由于在获取当前线程绑定事务的时候,有一个判断,如果存在当前线程绑定的Session,会把当前事务对象的newSessionHolder值设置成 false,从而跳过上面的代码中doCleanupAfterCompletion(status.getTransaction());的调用:

Java代码
  1. protected  Object doGetTransaction() {  
  2.         HibernateTransactionObject txObject = new  HibernateTransactionObject();  
  3.         txObject.setSavepointAllowed(isNestedTransactionAllowed());  
  4.   
  5.         if  (TransactionSynchronizationManager.hasResource(getSessionFactory())) {  
  6.             SessionHolder sessionHolder =  
  7.                     (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());  
  8.             if  (logger.isDebugEnabled()) {  
  9.                 logger.debug("Found thread-bound Session ["  +  
  10.                         SessionFactoryUtils.toString(sessionHolder.getSession()) + "] for Hibernate transaction" );  
  11.             }  
  12.             txObject.setSessionHolder(sessionHolder, false );  
  13.             if  (getDataSource() !=  null ) {  
  14.                 ConnectionHolder conHolder = (ConnectionHolder)  
  15.                         TransactionSynchronizationManager.getResource(getDataSource());  
  16.                 txObject.setConnectionHolder(conHolder);  
  17.             }  
  18.         }  
  19.   
  20.         return  txObject;  
  21.     }  
protected Object doGetTransaction() {
		HibernateTransactionObject txObject = new HibernateTransactionObject();
		txObject.setSavepointAllowed(isNestedTransactionAllowed());

		if (TransactionSynchronizationManager.hasResource(getSessionFactory())) {
			SessionHolder sessionHolder =
					(SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
			if (logger.isDebugEnabled()) {
				logger.debug("Found thread-bound Session [" +
						SessionFactoryUtils.toString(sessionHolder.getSession()) + "] for Hibernate transaction");
			}
			txObject.setSessionHolder(sessionHolder, false);
			if (getDataSource() != null) {
				ConnectionHolder conHolder = (ConnectionHolder)
						TransactionSynchronizationManager.getResource(getDataSource());
				txObject.setConnectionHolder(conHolder);
			}
		}

		return txObject;
	}



综合一下,只要使用Spring的TransactionManager来管理事务,就可以放心在HibernateDaoSupport中使用getSession(),释放的工作会有Spring帮你完成。

你可能感兴趣的:(spring,多线程,thread,Hibernate,配置管理)