使用hibernate資料庫連線不釋放的問題
阿新 • • 發佈:2019-01-05
最近同事遇到使用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() {......})這樣。