注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

北漂的小羊

Java编程,开发者,程序员,软件开发,编程,代码。新浪微博号:IT国子监

 
 
 

日志

 
 
关于我

在这里是面向程序员的高品质IT技术学习社区,是程序员学习成长的地方。让我们更好地用技术改变世界。请关注新浪微博号: IT国子监(http://weibo.com/itguozijian)

网易考拉推荐

Java 中Spring 中使用hibernate3前HibernateTemplate的源码分析  

2013-01-14 18:11:12|  分类: JAVA |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
在分析HibernateTemplate前,首先从网上了解下一些关于回调的一些概念。我相信在了解其原理实现的基础上,可以更好的进行开发和扩展,关键得理解其思想。
   软件模块之间总是存在着一定的接口,从调用方式上,可以把他们分为三类:同步调用、回调和异步调用。
   同步调用是一种阻塞式调用,调用方要等待对方执行完毕才返回,它是一种单向调用。(简单来说就是顺序执行啦。)
回调是一种双向调用模式,也就是说,被调用方在接口被调用时也会调用对方的接口。(个人觉得有点像模板方法的实现。)
   异步调用是一种类似消息或事件的机制,不过它的调用方向刚好相反,接口的服务在收到某种讯息或发生某种事件时,会主动通知客户方(即调用客户方的接口)。(差不多就是异步执行吧。)
   回调和异步调用的关系非常紧密,通常我们使用回调来实现异步消息的注册,通过异步调用来实现消息的通知。同步调用是三者当中最简单的,而回调又常常是异步调用的基础。
   由于本文章主要关注的是Java 的回调机制,所以其他就不介绍了。下面来看看Java 是怎么来实现回调机制的。
Java代码 
  1. package callback;  
  2. /** 
  3.  *  
  4.  * @author zhxing 
  5.  * @since 2010.4.16 
  6.  * 
  7.  */  
  8. public class Test{  
  9.     private Callback callback;  
  10.     public void setCallback(Callback callback){  
  11.         this.callback=callback;  
  12.     }  
  13.     //实际方法  
  14.     public void foo(){  
  15.         System.out.println("this is foo();");  
  16.         //在这里调用回调函数  
  17.         if(callback!=null){  
  18.             callback.doSomething();  
  19.         }  
  20.     }  
  21.     //测试  
  22.     public static void main(String[] args) {  
  23.         Test t=new Test();  
  24.         t.setCallback(new Callback(){  
  25.             public void doSomething() {  
  26.                 System.out.println("this is callback.");  
  27.             }  
  28.         });  
  29.           
  30.         t.foo();  
  31.     }  
  32.       
  33. }  
  34. //回调函数  
  35. interface Callback {  
  36.     void doSomething();  
  37. }  

 

 

   一般在我们数据库开发中,都会有打开和关闭数据、捕获异常等的一些固定的操作,写久了也就特别的反感了。是吧。。下面来利用回调简化数据库操作,例子很简单,对于数据的打开和关闭我只做了简单的描述。

Java代码 
  1. package callback;  
  2.   
  3. public class UserDao {  
  4.     private UserTemplate template=new UserTemplate();  
  5.       
  6.     //这个实际上也是用回调方法,不过在UserTemplate 进行了封装  
  7.     public void add(final String name){  
  8.         this.template.add(name);  
  9.     }  
  10.     //这个是用回调方法来实现的  
  11.     public String getName(){  
  12.         return (String)this.template.execute(new UserCallback(){  
  13.             public Object doSomething() {  
  14.                 System.out.println("成功读取数据库。。。name= zhxing");  
  15.                 return "zhxing";  
  16.             }     
  17.         });  
  18.     }  
  19.       
  20.     //测试  
  21.     public static void main(String[] args) {  
  22.         UserDao u=new UserDao();  
  23.         u.add("zhxing");  
  24.         System.out.println(u.getName());  
  25.     }  
  26. }  
  27.   
  28. package callback;  
  29. //回调函数的实现  
  30. public class UserTemplate {  
  31.     //调用回调函数,这里是不是有点像模板方法了,呵呵  
  32.     public  Object execute(UserCallback callback){  
  33.         System.out.println("打开数据库连接");  
  34.         Object o=callback.doSomething();  
  35.         System.out.println("关闭数据库连接");  
  36.         return o;  
  37.     }  
  38.       
  39.     //这里用来简化常用的操作  
  40.     public void add(final String name){  
  41.         execute(new UserCallback(){  
  42.             public Object doSomething() {  
  43.                 System.out.println("name="+name+" 成功加入数据库。。。");  
  44.                 return null;  
  45.             }     
  46.         });  
  47.     }  
  48.   
  49. }  
  50.   
  51. package callback;  
  52. //回调函数接口  
  53. public interface UserCallback {  
  54.     Object doSomething();  
  55. }  

 

 

    好了,进入正题吧。。来研究下Spring 中HibernateTemplate 是怎么实现了。。其实上面的那个例子已经可以说明全部了,呵呵。。下面我们按照开发的流程来进行一些源码分析。
    当我们用Spring+Hibernate实现Dao层的时候,一般会去继承HibernateDaoSupport这个类。
来分析下这个HibernateDaoSupport类(具体方法细节请查看源码):

Java代码 
  1. public abstract class HibernateDaoSupport extends DaoSupport {  
  2.   
  3.     private HibernateTemplate hibernateTemplate;  
  4.      //Set the Hibernate SessionFactory to be used by this DAO.  
  5.     public final void setSessionFactory(SessionFactory sessionFactory) {  
  6.     }  
  7.     protected HibernateTemplate createHibernateTemplate(SessionFactory sessionFactory) {  
  8.         }  
  9.     //返回这个HiberanteTemplate 中的成员变量SessionFactory  
  10.     public final SessionFactory getSessionFactory() {  
  11.           
  12.     }  
  13.   
  14.     public final void setHibernateTemplate(HibernateTemplate hibernateTemplate) {  
  15.         this.hibernateTemplate = hibernateTemplate;  
  16.     }  
  17.     public final HibernateTemplate getHibernateTemplate() {  
  18.       return this.hibernateTemplate;  
  19.     }  
  20. //检查HibernateTemplate是否为空,如果类中的HibernateTemplate未设置则会报错  
  21.     protected final void checkDaoConfig() {  
  22.         if (this.hibernateTemplate == null) {  
  23.             throw new IllegalArgumentException("'sessionFactory' or 'hibernateTemplate' is required");  
  24.         }  
  25.     }  
  26.   
  27.   
  28.     //获得Hibernate中的session,可以在HibernateTemplate中配置是否在Session没创建时新创建一个,在事务处理中很有用  
  29.     protected final Session getSession()  
  30.         throws DataAccessResourceFailureException, IllegalStateException {  
  31.   
  32.         return getSession(this.hibernateTemplate.isAllowCreate());  
  33.     }  
  34.   
  35.     //这里是获得Hibernate 的session 的主要方法  
  36.     protected final Session getSession(boolean allowCreate)  
  37.         throws DataAccessResourceFailureException, IllegalStateException {  
  38.   
  39.         return (!allowCreate ?  
  40.             SessionFactoryUtils.getSession(getSessionFactory(), false) :  
  41.                 SessionFactoryUtils.getSession(  
  42.                         getSessionFactory(),  
  43.                         this.hibernateTemplate.getEntityInterceptor(),  
  44.                         this.hibernateTemplate.getJdbcExceptionTranslator()));  
  45.     }  
  46.   
  47.     //把HibernateException异常转换成DataAccessException异常  
  48.     protected final DataAccessException convertHibernateAccessException(HibernateException ex) {  
  49.         return this.hibernateTemplate.convertHibernateAccessException(ex);  
  50.     }  
  51.   
  52.     //释放Hibernate 的session  
  53.     protected final void releaseSession(Session session) {  
  54.         SessionFactoryUtils.releaseSession(session, getSessionFactory());  
  55.     }  
  56.   
  57. }  

 

 

   从上面可知道,HibernateDaoSupport 的主要作用是获取Hibernate 的Session (如果直接用HibernateTemplate是没有办法获得Session 的)和管理HibernateTemplate。在Spring 中可以对直接继承该类,然后在Dao 的配置上就可以直接进行注入SessionFactory了,还可以直接从Dao中获取Hibernate的Session进行操作。
   现在回到正题,进行分析下HibernateTemplate,先看下他的成员变量有哪些。

Java代码 
  1. public class HibernateTemplate extends HibernateAccessor implements HibernateOperations {  
  2.     //是否在Session不存在的时候进行创建  
  3.     private boolean allowCreate = true;  
  4. //是否每次都生成新的Session  
  5.     private boolean alwaysUseNewSession = false;  
  6. //是不是用原生的Hibernate 的session而不是用它的代理  
  7.     private boolean exposeNativeSession = false;  
  8. //检查Hibernate 的session 是否为只读模式  
  9.     private boolean checkWriteOperations = true;  
  10. //缓存Query  
  11.     private boolean cacheQueries = false;  
  12. //设置Query缓存的名称  
  13.     private String queryCacheRegion;  
  14. //设置批量获取的大小  
  15.     private int fetchSize = 0;  
  16. //设置最大的数据集  
  17. private int maxResults = 0;  
  18. }  

 

   HibernateTemplate 封装了很多Hibernate 的原始的操作,但把Hibernate 的session设置为了protected,而不能在它的子类外进行获取。下面来看看我们最常用get 和save 方法。

Java代码 
  1. public Object get(Class entityClass, Serializable id) throws DataAccessException {  
  2.         return get(entityClass, id, null);  
  3.     }  
  4. //实际get调用这个方法,增加了一个锁模式。  
  5.     public Object get(final Class entityClass, final Serializable id, final LockMode lockMode)  
  6.             throws DataAccessException {  
  7. //这里就是我们上面讨论的回调方法了。。  
  8.         return executeWithNativeSession(new HibernateCallback() {  
  9.             public Object doInHibernate(Session session) throws HibernateException {  
  10.                 if (lockMode != null) {  
  11.                     return session.get(entityClass, id, lockMode);  
  12.                 }  
  13.                 else {  
  14.                     return session.get(entityClass, id);  
  15.                 }  
  16.             }  
  17.         });  
  18.     }  
  19.   
  20.     public Serializable save(final Object entity) throws DataAccessException {  
  21.     //这里也是用了回调,和上面一样的。  
  22.         return (Serializable) executeWithNativeSession(new HibernateCallback() {  
  23.             public Object doInHibernate(Session session) throws HibernateException {  
  24.                 checkWriteOperationAllowed(session);  
  25.                 return session.save(entity);  
  26.             }  
  27.         });  
  28.     }  

 

 

  下面来看看这个回调函数的方法。

Java代码 
  1. protected Object doExecute(HibernateCallback action, boolean enforceNewSession, boolean enforceNativeSession)  
  2.             throws DataAccessException {  
  3.   
  4.         Assert.notNull(action, "Callback object must not be null");  
  5. //判断是否强制新建Session  
  6.         Session session = (enforceNewSession ?  
  7.                 SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor()) : getSession());  
  8. //判断是否设置了事务且是否强制新建session  
  9.         boolean existingTransaction = (!enforceNewSession &&  
  10.                 (!isAllowCreate() || SessionFactoryUtils.isSessionTransactional(session, getSessionFactory())));  
  11.         if (existingTransaction) {  
  12.             logger.debug("Found thread-bound Session for HibernateTemplate");  
  13.         }  
  14.   
  15.         FlushMode previousFlushMode = null;  
  16.         try {  
  17. //设置并返回FlushMode  
  18.             previousFlushMode = applyFlushMode(session, existingTransaction);  
  19. //设置过滤器  
  20.             enableFilters(session);  
  21. //是否创建session 代理  
  22.             Session sessionToExpose =  
  23.                     (enforceNativeSession || isExposeNativeSession() ? session : createSessionProxy(session));  
  24. //这里调用回调函数了  
  25.             Object result = action.doInHibernate(sessionToExpose);  
  26.             flushIfNecessary(session, existingTransaction);  
  27.             return result;  
  28.         }  
  29.         catch (HibernateException ex) {  
  30.             throw convertHibernateAccessException(ex);  
  31.         }  
  32.         catch (SQLException ex) {  
  33.             throw convertJdbcAccessException(ex);  
  34.         }  
  35.         catch (RuntimeException ex) {  
  36.             // Callback code threw application exception...  
  37.             throw ex;  
  38.         }  
  39.         finally {  
  40.             if (existingTransaction) {  
  41.                 logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");  
  42.                 disableFilters(session);  
  43.                 if (previousFlushMode != null) {  
  44.                     session.setFlushMode(previousFlushMode);  
  45.                 }  
  46.             }  
  47.             else {  
  48.                 // Never use deferred close for an explicitly new Session.  
  49.                 if (isAlwaysUseNewSession()) {  
  50.                     SessionFactoryUtils.closeSession(session);  
  51.                 }  
  52.                 else {  
  53.             //把session绑定到线程变量中(ThreadLocal)     SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());  
  54.                 }  
  55.             }  
  56.         }  
  57.     }  

 

     到这里基本就简单分析完了,关于HibernateTemplate的其他操作,其实都差不多的,对Hibernate的一些常用操作进行了回调封装,可以自己分析下。

  评论这张
 
阅读(577)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2016