细谈Spring深入源码分析Spring之HibernateTemplate 和HibernateDaoSupport

Posted java那些事

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了细谈Spring深入源码分析Spring之HibernateTemplate 和HibernateDaoSupport相关的知识,希望对你有一定的参考价值。


spring提供访问数据库的有三种方式:

 

HibernateDaoSupport

HibernateTemplate(推荐使用)

jdbcTemplate(我们一般不用)


类所在包:

HibernateTemplateorg.springframework.orm.hibernate3.HibernateTemplate

HibernateDaoSupport:org.springframework.orm.hibernate3.support.HibernateDaoSupport


       spring如果想整合hibernate的话,首先就应该获得SessionFactory这个类,然后再通过获得session就可以进行访问数据库了,即spring提供的类HibernateDaoSupport,HibernateTemplate应该是有setSessionFactory,在使用的时候注入一下就可以了。HibernateTemplate类中的方法是spring封装了hibernate中的方法,在使用完了以后会自动释放session。而如果使用了HibernateDaoSupport的getSession方法,就需要配套的用releaseSession(Session session)或者session.close来关闭session,无法实现自动管理session。所以很多人都倾向于用spring的 Hibernatetemplate类或者HibernateDaoSupport的getHibernateTemplate方法来实现实现数据库的交互,当然,如果遇到hibernatetemplate无法实现的功能,可以使用 HibernateDaoSupport。


首先我们先来看一下HibernateTemplate类:

首先我们来说一下我们为什么要用HibernateTemplate,其实这个类就是我们平常使用hibernate进行dao操作的一个模版,我们不需要那些开头的开启事务、获得session,结尾的提交事务,关闭session等操作了,这些工作是HibernateTemplate都给我们封装好了,我们直接调用其dao的操作方法就可以了,并且他还给我们封装了hibernate的几乎所有的异常,这样我们在处理异常的时候就不要记住那么多繁琐的异常了。所以我们就叫他是一个hibernate中dao操作的模版,他提供的常用方法:


get 从数据库相关表中获取一条记录并封装返回一个对象(Object) 
load 作用与get基本相同,不过只有在对该对象的数据实际调用时,才会去查询数据库 
save 添加记录 
saveOrUpdate 判断相应记录是否已存在,据此进行添加或修改记录
update 修改记录 
delete 删除记录  


下面我们来看一下HibernateTemplate的源码来看一下他的具体方法是怎么样实现的,其实你观察源码可以发现,他所提供的方法几乎都是一个实现实现的。下面我们就以save方法来具体看一下:


[java]   

  1. public Serializable save(final Object entity) throws DataAccessException {  

  2. return (Serializable) executeWithNativeSession(new HibernateCallback() {  

  3. public Object doInHibernate(Session session) throws HibernateException {  

  4. checkWriteOperationAllowed(session);  

  5. return session.save(entity);  

  6. }  

  7. });}  




       我们从源码中可以发现,HibernateTemplate把我们hibernate的异常都封装成了一个DataAccessException 。好了,解释一下上面的代码,上面代码中主要是调用了executeWithNativeSession这个方法,其实这个方法就是给我们封装好的hibernate开头和结尾一些列操作,他需要一个参数,这个参数是一个回调的对象,其实这个对象是实现了一个HibernateCallback的接口,实现这个接口需要实现这个接口里面的方法doInHibernate,这个方法需要把当前的session传递过来,其实他就是把他原先模版里获得的session传过去。然后在在doInHibernate中利用模版中得到的session进行保存数据。其实我们调用save的过程就是给他传一个回调对象的过程,我们可以看到,他的回调对象是new出来的。


     如果你还没看懂的话,那大家来看一下下面我们实现自己的HibernateTemplate,他的思路和spring提供的基本是一样的:其中MyHibernateCallback 是一个简单接口:

[java]   

  1. import org.hibernate.Session;  

  2. public class MyHibernateTemplate {  

  3. public void executeWithNativeSession(MyHibernateCallback callback) {  

  4. Session s = null;  

  5. try {  

  6. s = getSession();  

  7. s.beginTransaction();  

  8. callback.doInHibernate(s);  

  9. s.getTransaction().commit();  

  10. catch (Exception e) {  

  11. s.getTransaction().rollback();  

  12. finally {  

  13. //...  

  14. }  

  15. }  

  16. private Session getSession() {  

  17. // TODO Auto-generated method stub  

  18. return null;  

  19. }  

  20. public void save(final Object o) {  

  21. new MyHibernateTemplate().executeWithNativeSession(new MyHibernateCallback() {  

  22. public void doInHibernate(Session s) {  

  23. s.save(o);  

  24. }  

  25. });  

  26. }  

  27. }  





    好了,原理我们介绍完了之后,下面我们来看一下具体应用,这个HibernateTemplate在我们的程序中怎么用,在上面我们也说过了,这个用法主要是把sessionfactory注入给我们的HibernateTemplate

首先我们来看一下beans.xml的配置:


[html]   

  1. <?xml version="1.0" encoding="UTF-8"?>  

  2. <beans xmlns="http://www.springframework.org/schema/beans"  

  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  

  4. xmlns:context="http://www.springframework.org/schema/context"  

  5. xmlns:aop="http://www.springframework.org/schema/aop"  

  6. xmlns:tx="http://www.springframework.org/schema/tx"  

  7. xsi:schemaLocation="http://www.springframework.org/schema/beans  

  8.            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  

  9.            http://www.springframework.org/schema/context  

  10.            http://www.springframework.org/schema/context/spring-context-2.5.xsd  

  11.            http://www.springframework.org/schema/aop  

  12.            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd  

  13.            http://www.springframework.org/schema/tx   

  14.            http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  

  15. <bean id="dataSource"  

  16. class="org.apache.commons.dbcp.BasicDataSource"  

  17. destroy-method="close">  

  18. <property name="driverClassName" value="com.mysql.jdbc.Driver" />  

  19. <property name="url" value="jdbc:mysql://localhost:3306/spring" />  

  20. <property name="username" value="root" />  

  21. <property name="password" value="bjsxt" />  

  22. </bean>  

  23. <bean id="sessionFactory"  

  24. class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">  

  25. <property name="dataSource" ref="dataSource" />  

  26. <property name="annotatedClasses">  

  27. <list>  

  28. <value>com.bjsxt.model.User</value>  

  29. <value>com.bjsxt.model.Log</value>  

  30. </list>  

  31. </property>  

  32. <property name="hibernateProperties">  

  33. <props>  

  34. <prop key="hibernate.dialect">  

  35. org.hibernate.dialect.MySQLDialect  

  36. </prop>  

  37. <prop key="hibernate.show_sql">true</prop>  

  38. </props>  

  39. </property>  

  40. </bean>  

  41. <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">  

  42. <property name="sessionFactory" ref="sessionFactory"></property>  

  43. </bean>  

  44. <bean id="UserDao" class="com.bzu.dao.userDao">  

  45. <property name="hibernateTemplate" ref="hibernateTemplate"></property>  

  46. </bean>  

  47. </beans>  




下一步我们来看一下hibernateTemplate的使用:

[html]   

  1. public class UserDAOImpl implements UserDAO {  

  2. private HibernateTemplate hibernateTemplate;  

  3. public HibernateTemplate getHibernateTemplate() {  

  4. return hibernateTemplate;  

  5. }  

  6. public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {  

  7. this.hibernateTemplate = hibernateTemplate;  

  8. }  

  9. public void save(User user) {  

  10. hibernateTemplate.save(user);  

  11. }}  




这基本上就是我们的hibernateTemplate原理及使用了,其实他的使用很简单


下面,我们来看一下HibernateDaoSupport:

通过上面我们可以看出,通过xml注入hibernateTemplate,我们可以想象的到所有DAO类中都会有HibernateTemplate的bean方法,于是上面hibernateTemplate的set、get的方法和xml配置会有大量的,于是就出现了代码冗余和重复,我们怎么才能避免这个重复呢,我们很容易应该能想到,把上面注入hibernateTemplate抽出一个类,然后让我们的dao类来继承这个类。不过这个类Spring已经有了,那就是HibernateDaoSupport,除此之外,HibernateDaoSupport也有SessionFactory的bean方法,所以我们在用HibernateDaoSupport的时候同样也要给我们注入sessionfactory或者hibernateTemplate,在用的时候你会发现HibernateDaoSupport也给我们提供了getHibernateDaoSupport方法。

相关配置示例:userdao继承了HibernateDaoSupport


[html]   

  1. <bean id="userdao" class="com.bzu.dao.uerdao">  

  2. <property name="sessionFactory" ref="sessionFactory"></property>  

  3. </bean>  





     用上面的方法我们可以发现一个问题,我们同样解决不了xml配置重复的问题,我们每一个dao都要在xml注入sessionfactory或者hibernateTemplate,解决这个问题的办法就是我们自己在抽出一个SuperDao类,让这个类去继承HibernateDaoSupport,然后我们给SuperDao类去配置,这样的话,我们在我的dao类中直接去继承SuperDao类就可以了,这样不管有多少dao类,只要继承SuperDao,我们就可以实现我们想要的功能了。



程序员内参
微信号:

programmer0001



推荐理由:
在这里,我们分享程序员相关技术,职场生活,行业热点资讯。不定期还会分享IT趣文和趣图。这里属于我们程序员自己的生活,工作和娱乐空间。


 ▼长按下方↓↓↓二维码识别关注


以上是关于细谈Spring深入源码分析Spring之HibernateTemplate 和HibernateDaoSupport的主要内容,如果未能解决你的问题,请参考以下文章

深入理解 spring 容器,源码分析加载过程

Spring Ioc源码深入剖析预备知识

深入理解Spring系列之十一:SpringMVC-@RequestBody接收json数据报415

深入浅出Spring原理及实战「源码调试分析」结合DataSourceRegister深入分析ImportBeanDefinitionRegistrar的源码运作流程

Spring之BeanFactory详解

深入源码分析Spring中的构造器注入