入门客AI创业平台(我带你入门,你带我飞行)
博文笔记

使用hibernate数据库连接不释放的问题

创建时间:2016-08-02 投稿人: 浏览次数:7792

最近同事遇到使用hibernate连接不释放的问题,代码大概是下面这样:

Query query = session.createQuery(hql);
for (int i = 0; i < values.length; i++) {
	query.setParameter(i, values[i]);
}
List result = query.setFirstResult(offset).setMaxResults(pageSize).list();

看了代码就知道原因了,明显没有关闭连接,所以才会出现连接不释放的问题,应当手动调用session.close()

如果不想每次都要手动关闭连接,最好就不要使用上面的这种用法。简单点的化可以借助于HibernateDaoSupport来完成数据方法的执行,方法是你可以写个DAO类继承HibernateDaoSupport类就可以了。

为什么这样就不会有连接不释放的问题?

看看HibernateDaoSupport源码,你会发现其方法基本上都是类似下面的结构:

getHibernateTemplate().execute(new HibernateCallback() {
	public Object doInHibernate(Session session) throws HibernateException {
		Query query = session.getNamedQuery(queryName);
		............
	}
});
可以看到实际上HibernateDaoSupport中的方法最终都是调用HibernateTemplate类的execute方法,而execute方法最终都会调用doExecute方法,下面是doExecute方法的源码,主要看看finally代码块部分,就是在这里关闭的连接

protected <T> T doExecute(HibernateCallback<T> action, boolean enforceNewSession, boolean enforceNativeSession)
			throws DataAccessException {

		Assert.notNull(action, "Callback object must not be null");

		Session session = (enforceNewSession ?
				SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession());
		boolean existingTransaction = (!enforceNewSession &&
				(!isAllowCreate() || 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 =
					(enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session));
			T 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 {//在finally中关闭了session
			if (existingTransaction) {
				logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
				disableFilters(session);
				if (previousFlushMode != null) {
					session.setFlushMode(previousFlushMode);
				}
			}
			else {
				// Never use deferred close for an explicitly new Session.
				if (isAlwaysUseNewSession()) {
					SessionFactoryUtils.closeSession(session);
				}
				else {
					SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
				}
			}
		}
	}

综上,如果你是手动创建Query,那你要用完后必须要将session手动关闭。如果你是直接使用HibernateDaoSupport中的方法,那么不需要手动关闭session。或者你调用HibernateTemplate的方法也没有问题,类似getHibernateTemplate().execute(new HibernateCallback() {......})这样。

声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。