spring管理hibernate session的问题探究

我们再用spring管理hibernate的时候, 我们会继承HibernateDaoSupport 或者HibernateTemplate类.

我们不知道这两个类之间有什么关系. 也没有去关闭session. 让我很是心不安,他可没有关闭session呀.如果..真的是后果不堪设想.百度了好久, 谷歌了好多. 都没有一个像样的说法. 说spring中HibernateDaoSupport会自己关闭session.

眼见为实.于是乎决定查看spring源码一探究竟.

先打开HibernateDaoSupoprt看看.

public abstract class HibernateDaoSupport extends DaoSupport {

	private HibernateTemplate hibernateTemplate;

 public final void setSessionFactory(SessionFactory sessionFactory) {
	  this.hibernateTemplate = createHibernateTemplate(sessionFactory);
	}

protected HibernateTemplate createHibernateTemplate(SessionFactory sessionFactory) {
		return new HibernateTemplate(sessionFactory);
	}
public final SessionFactory getSessionFactory() {
		return (this.hibernateTemplate != null ? this.hibernateTemplate.getSessionFactory() : null);
	}
public final void setHibernateTemplate(HibernateTemplate hibernateTemplate) {
		this.hibernateTemplate = hibernateTemplate;
	}
public final HibernateTemplate getHibernateTemplate() {
	  return hibernateTemplate;
	}
protected final void checkDaoConfig() {
		if (this.hibernateTemplate == null) {
			throw new IllegalArgumentException("sessionFactory or hibernateTemplate is required");
		}
	}
protected final Session getSession()
	    throws DataAccessResourceFailureException, IllegalStateException {

		return getSession(this.hibernateTemplate.isAllowCreate());
	}
protected final Session getSession(boolean allowCreate)
	    throws DataAccessResourceFailureException, IllegalStateException {

		return (!allowCreate ?
		    SessionFactoryUtils.getSession(getSessionFactory(), false) :
				SessionFactoryUtils.getSession(
						getSessionFactory(),
						this.hibernateTemplate.getEntityInterceptor(),
						this.hibernateTemplate.getJdbcExceptionTranslator()));
	}
protected final DataAccessException convertHibernateAccessException(HibernateException ex) {
		return this.hibernateTemplate.convertHibernateAccessException(ex);
	}
protected final void releaseSession(Session session) {
		SessionFactoryUtils.releaseSession(session, getSessionFactory());
	}

 

在这里我们会注意到一个private 对象. 那就是HibernateTemplate. 这里面也有一个HibernateTemplate的set. get.

 

哦: 原来如此.呵呵,很白痴的事.

比如说. BaseDao extends HibernateDaoSupport 我们会super.getHibernateTemplate.find(hql);

                                                                                    super.getHibernateTemplate.save(obj);

        和BaseDao extends HibernateTemplate 中super.find(hql)和super.save(obj);是等效的.  原来没有思考害的我改了一个多小时. 汗..

 

下面我们来看看HibernateTemplate是怎么样来操作session的呢.

照样我们贴出源代码. 由于这个类代码较多. 我只贴出来几个代表性的属性和方法, 供大家参考.

 

public class HibernateTemplate extends HibernateAccessor implements HibernateOperations {

 private boolean allowCreate = true;

 private boolean alwaysUseNewSession = false;

 private boolean exposeNativeSession = false;

 private boolean checkWriteOperations = true;

 private boolean cacheQueries = false;

 private String queryCacheRegion;

 private int fetchSize = 0;

 private int maxResults = 0;

 

 public void ......();

} 一系列的方法.

 

下面我们看看save()方法.

 

public Serializable save(final Object entity) throws DataAccessException {
		return (Serializable) execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException {
				checkWriteOperationAllowed(session);
				return session.save(entity);
			}
		}, true);
	}

 

 我们再看看update(), merge(), find()等方法的源码.

 

//update 方法

public void update(Object entity) throws DataAccessException {
		update(entity, null);
	}

	public void update(final Object entity, final LockMode lockMode) throws DataAccessException {
		execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException {
				checkWriteOperationAllowed(session);
				session.update(entity);
				if (lockMode != null) {
					session.lock(entity, lockMode);
				}
				return null;
			}
		}, true);
	}


//merge()

public Object merge(final Object entity) throws DataAccessException {
		return execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException {
				checkWriteOperationAllowed(session);
				return session.merge(entity);
			}
		}, true);
	}

//find()
public List find(String queryString) throws DataAccessException {
		return find(queryString, (Object[]) null);
	}

	public List find(String queryString, Object value) throws DataAccessException {
		return find(queryString, new Object[] {value});
	}

	public List find(final String queryString, final Object[] values) throws DataAccessException {
		return (List) execute(new HibernateCallback() {
			public Object doInHibernate(Session session) throws HibernateException {
				Query queryObject = session.createQuery(queryString);
				prepareQuery(queryObject);
				if (values != null) {
					for (int i = 0; i < values.length; i++) {
						queryObject.setParameter(i, values[i]);
					}
				}
				return queryObject.list();
			}
		}, true);
	}

 

 细心的朋友们可能发现了. 他们无一例外的都调用了一个叫做execute()的方法. 对了. 我们再看看execute的面目.到底他干了一件什么样的事情呢?]

public Object execute(HibernateCallback action, boolean exposeNativeSession) throws DataAccessException {
		Session session = getSession();
		boolean existingTransaction = SessionFactoryUtils.isSessionTransactional(session, getSessionFactory());
		if (existingTransaction) {
			logger.debug("Found thread-bound Session for HibernateTemplate");
		}

		FlushMode previousFlushMode = null;
		try {
			previousFlushMode = applyFlushMode(session, existingTransaction);
			enableFilters(session);
			Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));
			Object result = action.doInHibernate(sessionToExpose);
			flushIfNecessary(session, existingTransaction);
			return result;
		}
		catch (HibernateException ex) {
			throw convertHibernateAccessException(ex);
		}
		catch (SQLException ex) {
			throw convertJdbcAccessException(ex);
		}
		catch (RuntimeException ex) {
			// Callback code threw application exception...
			throw ex;
		}
		finally {
			if (existingTransaction) {
				logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
				disableFilters(session);
				if (previousFlushMode != null) {
					session.setFlushMode(previousFlushMode);
				}
			}
			else {
				SessionFactoryUtils.releaseSession(session, getSessionFactory());
			}
		}
	}

 

 

    抛掉其他的不管. finally中我们可以看到. 如果existingTransaction 他会

logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
disableFilters(session);
if (previousFlushMode != null) {
session.setFlushMode(previousFlushMode);
}

他并没有立即关闭session.

否则
SessionFactoryUtils.releaseSession(session, getSessionFactory());

他释放掉了session . 真的close()了吗?

我们在看看sessionFactoryUtil.的releaseSession()

 

public static void releaseSession(Session session, SessionFactory sessionFactory) {
		if (session == null) {
			return;
		}
		// Only close non-transactional Sessions.
		if (!isSessionTransactional(session, sessionFactory)) {
			closeSessionOrRegisterDeferredClose(session, sessionFactory);
		}
	}

 static void closeSessionOrRegisterDeferredClose(Session session, SessionFactory sessionFactory) {
  Map holderMap = (Map) deferredCloseHolder.get();
  if (holderMap != null && sessionFactory != null && holderMap.containsKey(sessionFactory)) {
   logger.debug("Registering Hibernate Session for deferred close");
   Set sessions = (Set) holderMap.get(sessionFactory);
   sessions.add(session);
   if (!session.isConnected()) {
    // We're running against Hibernate 3.1 RC1, where Hibernate will
    // automatically disconnect the Session after a transaction.
    // We'll reconnect it here, as the Session is likely gonna be
    // used for lazy loading during an "open session in view" pase.
    session.reconnect();
   }
  }
  else {
   doClose(session);
  }
 }
	private static void doClose(Session session) {
		if (session != null) {
			logger.debug("Closing Hibernate Session");
			try {
				session.close();
			}
			catch (HibernateException ex) {
				logger.error("Could not close Hibernate Session", ex);
			}
			catch (RuntimeException ex) {
				logger.error("Unexpected exception on closing Hibernate Session", ex);
			}
		}
	}

 

 


    呵呵, 現在終於心安裡德的去睡覺了.  因为他真的关了.

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值