自動生成hibernate配置檔案的時候,會在dao層用到getSession()方法來操作資料庫記錄,但是他
還有個方法getHibernateTemplate(),這兩個方法究竟有什麼差別呢?
1.使用getSession()方法你隻要繼承sessionFactory,而使用getHibernateTemplate()方法必須繼承HibernateDaoSupport當然包括sessionFactory,這點差別都不是特别重要的,下面這些差別就很重要了
2.getSession()方法是沒有經過spring包裝的,spring會把最原始的session給你,在使用完之後必須自己調用相應的close方法,而且也不會對聲明式事務進行相應的管理,一旦沒有及時關閉連接配接,就會導緻資料庫連接配接池的連接配接數溢出,getHibernateTemplate()方法是經過spring封裝的,例如添加相應的聲
明式事務管理,由spring管理相應的連接配接。
在實際的使用過程中發現的确getHibernateTemplate()比getSession()方法要好很多,但是有些方法在getHibernateTemplate()并沒有提供,這時我們用HibernateCallback 回調的方法管理資料庫.
例如如下代碼:
public List getListForPage ( final String hql , final int offset , final int length ) { List list = getHibernateTemplate().executeFind ( new HibernateCallback ( ) {
public Object doInHibernate ( Session session ) throws HibernateException,
SQLException {
Query query = session.createQuery ( hql )
query.setFirstResult ( offset ) query.setMaxResults ( length )
List list = query.list ( )
return list
} }) return list
}
總的來說getHibernateTemplate()要優于getSession(),因為前者是後者的封裝,樓主可以去看源碼,
這裡面的各種操作,比如find、update等操作,就是回調的hibernate的方法。
getSession()這種直接使用Hibernate通路代碼的好處在于它允許你在資料通路代碼中抛出 任何 checked exception,而 HibernateTemplate 卻受限于回調中的unchecked exception。 注意,你通常可以将這些應用程式的異常處理推遲到回調函數之後,這樣,你依然可以正常使用 HibernateTemplate。 一般來說,
HibernateTemplate 類所提供的許多方法在許多情況下看上去更簡單和便捷。
getSession()這個方法本身其實傳回的是與目前事務綁定的Session對象,在HibernateDaoSupport中使用,HibernateDaoSupport本身是不負責對這個Session對象進行關閉的,是以在其中有一個對應的
releaseSession()方法,用于關閉Session。
但是一般使用Spring時,我們會采用HibernateTransactionManager進行事務管理,把事務配置在Service層。此時,它會幫助我們關閉與目前事務綁定的Session對象,這個可以參照HibernateTransactionManager類中的doCleanupAfterCompletion方法,它是一個抽象方法的實作。再追溯上去,會發現,在事務commit
或者rollback的時候,會有一段finally代碼,專門調用執行該方法的代碼:
Java代碼
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(
)); } } Java代碼 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(
)); } }
finally {
cleanupAfterCompletion(status);
}
private void cleanupAfterCompletion(DefaultTransactionStatus
status) {
status.setCompleted();
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.clearSynchronization();
TransactionSynchronizationManager.setCurrentTransactionName(n
ull);
TransactionSynchronizationManager.setCurrentTransactionReadOn
ly(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代碼
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;
} Java代碼
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.<SPAN class=hilite4><SPAN style="BACKG
ROUND-COLOR: #00ffff">getSession</SPAN></SPAN>()) + "] for Hibernate transaction");
}
txObject.setSessionHolder(sessionHolder, false);
if (getDataSource() != null) {
ConnectionHolder conHolder = (ConnectionHolder)
TransactionSynchronizationManager.getResource(getDataSource());
txObject.setConnectionHolder(conHolder);
} }
return txObject;
}
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幫你完成。