HibernateTransactionManager 和 hibernateTemplate的区别

来源:互联网 发布:ubuntu设置默认启动项 编辑:程序博客网 时间:2024/04/24 10:19
HibernateTransactionManager
管理事务嵌套,开启,关闭,资源线程同步,提交,回滚
HibernateTemplate是可以感知到线程内的事务和资源(存放在RESOURCESYCHRONIZEDMANAGER貌似叫这个,由AbstractPlatformTransactionManager)
Session s = sessionFactory.getCurrentSession();

sessionFactory.getCurrentSession()无法感知到SPRING开启的事务和资源(SESSION)


在applicationContext.xml中有如下配置:

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>


也可以:
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>

两种实现方式其实没有区别,尤其是第二种不要自己去关闭session,session在事务结束后都会自动关闭。



DataSource ->SessionFactory-> HibernateTranscationManager
Hibernate中通过SessionFactory创建和维护Session。Spring对SessionFactory的配置进行了整合,无需再通过Hibernate.cfg.xml对SessionFactory进行设定。SessionFactory节点的mappingResources属性包含了映射文件的路径,list节点下可配置多个映射文件。hibernateProperties节点则容纳了所有的属性配置。可以对应传统的Hibernate.cfg.xml文件结构对这里的SessionFactory配置进行解读。

如果一个方法中既用了HibernateTemplate,又用了JdbcTemplate,应该怎么配单实例的db事务呢(多例免谈)用 DataSouceTransactionManager是不行的,而用HibernateTransactionManager就可以保证
原因的话看下它们源代码,会发现HibernateTransactionManager中的处理可以保证SessionFactoryUtil和datasourceutil都能在一个事务里取到同一个连接


所以如果使用hibernateTransactionManager的话,就完全可以保证SessionFactoryUtil和datasourceutil都能在一个事务里取到同一个连接!所有的疑问烟消云散了,
所以大家还是使用hibernateTransactionManager从而随心所欲的使用jdbctemplate和hibernatetemplate吧

    下面是HibernateSessionFactory 和 HibernateTransactionManager的配置:

    在applicationContext-hibernate.xml中:

1<bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"> 2    <property name="dataSource"><ref bean="dataSource"/></property> 3    <property name="mappingResources"> 4        <list> 5            <value>com/mycompany/model/User.hbm.xml</value> 6                …………………………… 7        </list> 8    </property> 9    <property name="hibernateProperties">10    <props>11        <prop key="hibernate.dialect">@HIBERNATE-DIALECT@</prop>12        <!--prop key="hibernate.show_sql">true</prop-->13        <!--prop key="hibernate.hbm2ddl.auto">update</prop-->14    </props>15    </property>16</bean>


    Spring 提供了一个 HibernateTransactionManager,采用面向Hibernate的TransactionManager实现:org.springframework.orm.hibernate.HibernateTransactionManager。他用线程捆绑了一个Hibernate Session,用它来支持transactions。
1<bean id="transactionManager" 2     class="org.springframework.orm.hibernate.HibernateTransactionManager">3     <property name="sessionFactory"><ref local="sessionFactory"/></property>4 </bean>


sessionFactory Bean引用了HibernateSessionFactory,而transactionManager Bean引用了HibernateTransactionManage。 transactionManager Bean中有个sessionFactory属性。 HibernateTransactionManager有个sessionFactory setter 和 getter方法,用来在Spring启动的时候实现“依赖注入” (dependency injection)的。 在sessionFactory 属性里引用sessionFactory Bean。这两个对象在Spring容器初始化后就被组装了起来了。
  
    User使用一个TransactionProxyFactoryBean,它定义了一个setTransactionManager()。能很方便的处理申明的事物还有Service Object。TransactionProxyFactoryBean 还有个setter. 这会被Business service object(UserManager)引用, UserManager定义了业务层,并且它还有个属性,由setUserDAO()引用。

DataSource->SessionFactory->HibernateTemplate->HibernateDaoSupport


    系统持久层中所有的类都继承自Spring提供的HibernateDaoSupport类,HibernateSupport实现了HibernateTemplate和SessionFactory实例的关联。HibernateTemplate对Hibernate Session操作进行了封装,提供了一个简单的方式实现了Hibernate-based DAO对象。借助HibernateTemplate我们可以脱离每次数据操作必须首先获得Session实例、启动事务、提交/回滚事务以及烦杂的try/catch/finally的繁琐操作。一个简单的Hibernate访问方法就完全解决了些麻烦! 无论是在多个DAO接口还是在多方事务的情况下,Spring使得多种DAO对象无缝地协同工作。

Spring为Hibernate的DAO提供工具类:HibernateDaoSupport。该类主要提供如下两个方法,方便DAO的实现:

     
public final HibernateTemplate getHibernateTemplate()      public final void setSessionFactory(SessionFactory sessionFactory)

其中,setSessionFactory方法用来接收Spring的ApplicationContext的依赖注入,可接收配置在Spring的SessionFactory实例,getHibernateTemplate方法则用来根据刚才的SessionFactory产生Session,最后生成HibernateTemplate来完成数据库访问。


    对于简单的单步的动作,象find, load, saveOrUpdate或者delete的调用,HibernateTemplate提供更为便利的选择以代替象一行的回调的执行。此外HibernateDaoSupport类提供了setSessionFactory方法来接受一个SessionFactory,同时提供了getSessionFactory和getHibernateTemplate方法供其继承类使用。将这些结合起来,允许对于典型的需求给出了非常简单的DAO实现,如获得所有用户的方法:
   
public List getUsers(User user) {        return getHibernateTemplate().find("from User u order by upper(u.username)");    } HibernateTemplate:public void saveUser(Person person){ 4 5              getHibernateTemplate().saveOrUpdate(person); 6 7         }

采用事物配置,我们就不需要写那么多的try catch和finally了,因为容器会自动帮我们在执行方法前给我们加上。

<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">    <property name="sessionFactory">       <ref bean="sessionFactory"/>    </property></bean>


也可以:
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTransactionManager">    <property name="sessionFactory">       <ref bean="sessionFactory"/>    </property></bean>


两种实现方式其实没有区别,尤其是第二种不要自己去关闭session,session在事务结束后都会自动关闭。 但是一定要注意延迟加载的问题,当对象在session关闭前没有从数据库中取得,而jsp中需要展示对象时,会提示LazyInitializationException,你可以通过
OpenSessionInViewFilter来保证延迟加载不会出现错误,即:<filter>     <filter-name>opensession</filter-name>     <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class></filter><filter-mapping>     <filter-name>opensession</filter-name>     <url-pattern>*.do</url-pattern></filter-mapping>


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

HibernateDaoSupport

HibernateTemplate(推荐使用)

jdbcTemplate(我们一般不用)



类所在包:

HibernateTemplate:org.springframework.orm.hibernate3.HibernateTemplateHibernateDaoSupport: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] view plaincopyprint?public Serializable save(final Object entity) throws       DataAccessException {      return (Serializable) executeWithNativeSession(new  HibernateCallback() {      public Object doInHibernate(Session session) throws HibernateException {      checkWriteOperationAllowed(session);      return session.save(entity);      }  });}  public Serializable save(final Object entity) throws DataAccessException {    return (Serializable) executeWithNativeSession(new HibernateCallback() {    public Object doInHibernate(Session session) throws      HibernateException {    checkWriteOperationAllowed(session);    return session.save(entity);    }});}


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

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


[java] view plaincopyprint?import org.hibernate.Session;  public class MyHibernateTemplate {  public void executeWithNativeSession(MyHibernateCallback callback) {      Session s = null;      try {          s = getSession();          s.beginTransaction();          callback.doInHibernate(s);          s.getTransaction().commit();      } catch (Exception e) {          s.getTransaction().rollback();      } finally {          //...       }  }  private Session getSession() {      // TODO Auto-generated method stub       return null;  }  public void save(final Object o) {      new MyHibernateTemplate().executeWithNativeSession(new  MyHibernateCallback() {          public void doInHibernate(Session s) {              s.save(o);          }      });  }  }  import org.hibernate.Session;public class MyHibernateTemplate {public void executeWithNativeSession(MyHibernateCallback callback) {Session s = null;try {s = getSession();s.beginTransaction();callback.doInHibernate(s);s.getTransaction().commit();} catch (Exception e) {s.getTransaction().rollback();} finally {//...}}private Session getSession() {// TODO Auto-generated method stubreturn null;}public void save(final Object o) {new MyHibernateTemplate().executeWithNativeSession(new MyHibernateCallback() {public void doInHibernate(Session s) {s.save(o);}});}}


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

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

[html] view plaincopyprint?01.<?xml version="1.0" encoding="UTF-8"?>  02.<beans xmlns="http://www.springframework.org/schema/beans"  03.xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  04.xmlns:context="http://www.springframework.org/schema/context"  05.xmlns:aop="http://www.springframework.org/schema/aop"  06.xmlns:tx="http://www.springframework.org/schema/tx"  07.xsi:schemaLocation="http://www.springframework.org/schema/beans  08.           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  09.           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="http://zhb0917.iteye.com/blog/com.mysql.jdbc.Driver" />  19.<property name="url" value="http://zhb0917.iteye.com/blog/jdbc:mysql://localhost:3306/spring" />  20.<property name="username" value="http://zhb0917.iteye.com/blog/root" />  21.<property name="password" value="http://zhb0917.iteye.com/blog/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>  <?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd           http://www.springframework.org/schema/context           http://www.springframework.org/schema/context/spring-context-2.5.xsd           http://www.springframework.org/schema/aop           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd           http://www.springframework.org/schema/tx            http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"><bean id="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close"><property name="driverClassName" value="http://zhb0917.iteye.com/blog/com.mysql.jdbc.Driver" /><property name="url" value="http://zhb0917.iteye.com/blog/jdbc:mysql://localhost:3306/spring" /><property name="username" value="http://zhb0917.iteye.com/blog/root" /><property name="password" value="http://zhb0917.iteye.com/blog/bjsxt" /></bean><bean id="sessionFactory"class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"><property name="dataSource" ref="dataSource" /><property name="annotatedClasses"><list><value>com.bjsxt.model.User</value><value>com.bjsxt.model.Log</value></list></property><property name="hibernateProperties"><props><prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop><prop key="hibernate.show_sql">true</prop></props></property></bean><bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"><property name="sessionFactory" ref="sessionFactory"></property></bean><bean id="UserDao" class="com.bzu.dao.userDao"><property name="hibernateTemplate" ref="hibernateTemplate"></property></bean></beans>


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

[html] view plaincopyprint?01.public class UserDAOImpl implements UserDAO {  02.private HibernateTemplate hibernateTemplate;  03.public HibernateTemplate getHibernateTemplate() {  04.return hibernateTemplate;  05.}  06.public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {  07.this.hibernateTemplate = hibernateTemplate;  08.}  09.public void save(User user) {  10.hibernateTemplate.save(user);  11.}}  public class UserDAOImpl implements UserDAO {private HibernateTemplate hibernateTemplate;public HibernateTemplate getHibernateTemplate() {return hibernateTemplate;}public void setHibernateTemplate(HibernateTemplate hibernateTemplate) {this.hibernateTemplate = hibernateTemplate;}public void save(User user) {hibernateTemplate.save(user);}}



这基本上就是我们的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] view plaincopyprint?01.<bean id="userdao" class="com.bzu.dao.uerdao">  02.<property name="sessionFactory" ref="sessionFactory"></property>  03.</bean>  <bean id="userdao" class="com.bzu.dao.uerdao"><property name="sessionFactory" ref="sessionFactory"></property></bean>


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

0 0
原创粉丝点击