HibernateTemplate回调

学习了spring的HibernateTemplate类部分源码,总结一下自己对回调模式的理解。

在dao里经常有这样的语句

代码

 

 

  1. public E findById(Serializable id)   
  2.     {   
  3.         return (E) getHibernateTemplate().get(clazz, id);   
  4.     }   

 

HibernateTemplate类源码

 

代码

 

 

  1. public Object get(Class entityClass, Serializable id) throws DataAccessException {   
  2.         return get(entityClass, id, null);   
  3.     }   

 

代码

 

 

  1. public Object get(final Class entityClass, final Serializable id, final LockMode lockMode)   
  2.             throws DataAccessException {   
  3.   
  4.         return execute(new HibernateCallback() {   
  5.             public Object doInHibernate(Session session) throws HibernateException {   
  6.                 if (lockMode != null) {    
  7.                     return session.get(entityClass, id, lockMode);   
  8.                 }   
  9.                 else {   
  10.                     return session.get(entityClass, id);   
  11.                 }   
  12.             }   
  13.         }, true);   
  14.     }   

 

代码

 

 

  1. public Object execute(HibernateCallback action) throws DataAccessException {   
  2.         return execute(action, isExposeNativeSession());   
  3.     }   

 

代码

 

 

  1. public Object execute(HibernateCallback action, boolean exposeNativeSession) throws DataAccessException {   
  2.         Assert.notNull(action, "Callback object must not be null");   
  3.   
  4.         Session session = getSession();   
  5.         boolean existingTransaction = SessionFactoryUtils.isSessionTransactional(session, getSessionFactory());   
  6.         if (existingTransaction) {   
  7.             logger.debug("Found thread-bound Session for HibernateTemplate");   
  8.         }   
  9.   
  10.         FlushMode previousFlushMode = null;   
  11.         try {   
  12.             previousFlushMode = applyFlushMode(session, existingTransaction);   
  13.             enableFilters(session);   
  14.             Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));   
  15.             Object result = action.doInHibernate(sessionToExpose);          flushIfNecessary(session, existingTransaction);   
  16.             return result;   
  17.         }   
  18.         catch (HibernateException ex) {   
  19.             throw convertHibernateAccessException(ex);   
  20.         }   
  21.         catch (SQLException ex) {   
  22.             throw convertJdbcAccessException(ex);   
  23.         }   
  24.         catch (RuntimeException ex) {   
  25.             // Callback code threw application exception...   
  26.             throw ex;   
  27.         }   
  28.         finally {   
  29.             if (existingTransaction) {   
  30.                 logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");   
  31.                 disableFilters(session);   
  32.                 if (previousFlushMode != null) {   
  33.                     session.setFlushMode(previousFlushMode);   
  34.                 }   
  35.             }   
  36.             else {   
  37.                 // Never use deferred close for an explicitly new Session.   
  38.                 if (isAlwaysUseNewSession()) {   
  39.                     SessionFactoryUtils.closeSession(session);   
  40.                 }   
  41.                 else {   
  42.                     SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());   
  43.                 }   
  44.             }   
  45.         }   
  46.     }   

 

 

HibernateTemplate类是对hibernate操作的封装。如果要自己写hibernate的操作,最麻烦的是那些要检查的错误,而且每一个地方都一样。不一样的地方只是真正对数据库操作的语句。spring的想法是一样的代码抽取出来写成一个HibernateTemplate中的execute方法。execute的方法参数是HibernateCallback接口类。HibernateCallback里面定义了一个doInHibernate的方法。因为这个方法是变的。比如你是查找数据方法应该就是:session.load()。删除数据就是session.delete().这样的话查询数据库的方法用execute方法。

HibernateCallback 接口类

代码

 

 

  1. public interface HibernateCallback {   
  2.   
  3.     Object doInHibernate(Session session) throws HibernateException, SQLException;   
  4. }  

 

然后使用内部类的形式把HibernateCallback中的方法doInHibernate实例化。

代码

 

 

  1. new HibernateCallback() {   
  2.             public Object doInHibernate(Session session) throws HibernateException {   
  3.                 if (lockMode != null) {    
  4.                     return session.get(entityClass, id, lockMode);   
  5.                 }   
  6.                 else {   
  7.                     return session.get(entityClass, id);   
  8.                 }   
  9.             }   

 

总的想法就是不变的东西可以抽象出一个方法。比如对异常的检查。变的东西,比如对数据库的操作,抽象出一个接口的方法。

总结

JAVA的CALLBACK通过接口来实现。

例:

1.HibernateTemplate,内联类

2.内联类实现接口HibernateCallback的doInHibernate 方法

3.HibernateTemplate拥有一个参数为HibernateCallback接口类型的函数execute(HibernateCallback action)方法.

4.调用HibernateTemplate的get方法时,将内联类传给了excute方法

5.执行excute方法时,(你调用它)

已取得内联类,就可以随时回调它所实现的HibernateCallback接口中的方法了,

这时它反过来调用你的方法(它调用你),这就是回调了.

Javaeye两个会员的理解,我觉得比较到位.

冉翔:

就是调用系统的一个方法,传进去一个接口的实现类 or 匿名类。

然后系统的方法调用接口申明的方法,并且注入相应的参数

Buaawhl:

IoC, Functor, Visitor 都是 callback。

就是一个 Template Methond 里面的flow不变,某一个步骤的具体操作变化,这个变化部需要  从外部(参数,或者属性,或者 override parent method)注入。

类似于从前的 C 回调函数指针。

[code]MainFlow ( callback ){

step1;

....

callback( someThing );

....

stepN;

}

 

注意配置文件里applictionContext.xml

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  <property name="sessionFactory"><ref local="sessionFactory"/></property>
 </bean>


 <bean id="baseTransactionProxy" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
  <property name="transactionManager">
   <ref bean="transactionManager" />
  </property>
  <property name="transactionAttributes">
  <props>
   <prop key="save*">PROPAGATION_REQUIRED</prop>
   <prop key="update*">PROPAGATION_REQUIRED</prop>
   <prop key="find*">PROPAGATION_REQUIRED</prop>
   <prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
  </props>
  </property>
 </bean> 

你可能感兴趣的:(spring,Hibernate,session,null,action,callback)