getHibernateTemplate()和getSession()的区别



自动生成hibernate配置文件的时候,会在dao层用到getSession()方法来操作数据库记录,但是他
还有个方法getHibernateTemplate(),这两个方法究竟有什么区别呢?
1.使用getSession()方法你只要继承sessionFactory,而使用getHibernateTemplate()方法必须继承HibernateDaoSupport当然包括sessionFactory,这点区别都不是特别重要的,下面这些区别就很重要了
2.getSession()方法是没有经过spring包装的,spring会把最原始的session给你,在使用完之后必须自己调用相应的close方法,而且也不会对声明式事务进行相应的管理,一旦没有及时关闭连接,就会导致数据库连接池的连接数溢出,getHibernateTemplate()方法是经过spring封装的,例如添加相应的声
明式事务管理,由spring管理相应的连接。
在实际的使用过程中发现的确getHibernateTemplate()比getSession()方法要好很多,但是有些方法在getHibernateTemplate()并没有提供,这时我们用HibernateCallback 回调的方法管理数据库.
例如如下代码:
/**
     * 使用 hql 语句进行操作
     * @param hql HSQL 查询语句(使用回调函数访问外部变量,必须是final的)
     * @param offset 开始取数据的下标     * @param length 读取数据记录数
    * @return List 结果集
*/
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.getSession()) + "] 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帮你完成。

你可能感兴趣的:(数据库)