`

HibernateTransactionManager事务管理

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

原文如下=====================================================================

今天这边报出一个问题,他在一个service方法里面,用了jdbcdaosupport的dao又用了hibernateDaoSupport的dao,在spring里面给service方法配上了事务,

但是通过mysql的bin log,发现这种不同的dao使用的连接id不是同一个,即jdbctemplate使用了一个链接,而hibernatetemplate使用了另外一个链接,这样虽然两种dao都是针对一个mysql实例,但却没法保证事务。

之前xd提过使用hibernateTransaction manager,可以保证混用时候的事务,但是却不知道为啥会这样。我们这边就以为datasourcetransactionmanager也是一样,但发现事实上不一样。确实我们换成hibernateTransaction manager,两种dao使用的connection就归一了,真好,但是为啥呢?

翻了半天spring的源代码终于找到了。

以下是datasourceTransactionManager的doGetTransaction和doBegin代码

protected Object doGetTransaction() {

//只是设定一个dataSource为key的存放connection的threadlcal
   DataSourceTransactionObject txObject = new DataSourceTransactionObject();
   txObject.setSavepointAllowed(isNestedTransactionAllowed());
   ConnectionHolder conHolder =
      (ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
   txObject.setConnectionHolder(conHolder, false);
   return txObject;
}

protected void doBegin(Object transaction, TransactionDefinition definition) {
     .....

   try {
    if (txObject.getConnectionHolder() == null ||
      txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
     Connection newCon = this.dataSource.getConnection();
    }

....
//从datasource拿一个连接,放入thread生命周期的holder

}


这就完了。

然后jdbctemplate会通过datasourceutil去拿这个holder里面的connection

从而在一个事务里使用这个连接。

但是hibernateTransactionManager呢:

protected Object doGetTransaction() {
   HibernateTransactionObject txObject = new HibernateTransactionObject();
   txObject.setSavepointAllowed(isNestedTransactionAllowed());

   SessionHolder sessionHolder =
     (SessionHolder) TransactionSynchronizationManager.getResource(getSessionFactory());
   if (sessionHolder != null) {
    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;
}

//两个holder都管!

protected void doBegin(Object transaction, TransactionDefinition definition) {
     .....

   try {
    if (txObject.getSessionHolder() == null || txObject.getSessionHolder().isSynchronizedWithTransaction()) {
     Interceptor entityInterceptor = getEntityInterceptor();
     Session newSession = (entityInterceptor != null ?
       getSessionFactory().openSession(entityInterceptor) : getSessionFactory().openSession());
     if (logger.isDebugEnabled()) {
      logger.debug("Opened new Session [" + SessionFactoryUtils.toString(newSession) +
        "] for Hibernate transaction");
     }
     txObject.setSessionHolder(new SessionHolder(newSession), true);
    }

    .....
    //从sessionFactory拿个新session,也会产生一个新连接

    session = txObject.getSessionHolder().getSession();

    if (this.prepareConnection && isSameConnectionForEntireSession(session)) {
     // We're allowed to change the transaction settings of the JDBC Connection.
     if (logger.isDebugEnabled()) {
      logger.debug(
        "Preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]");
     }

     //原来直接把session后面的connection也放入holder
     Connection con = session.connection();
     Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
     txObject.setPreviousIsolationLevel(previousIsolationLevel);
    }

所以如果使用hibernateTransactionManager的话,就完全可以保证SessionFactoryUtil和datasourceutil都能在一个事务里取到同一个连接!所有的疑问烟消云散了,
所以大家还是使用hibernateTransactionManager从而随心所欲的使用jdbctemplate和hibernatetemplate吧
分享到:
评论
4 楼 q364035622 2013-05-08  
                          
3 楼 raymondwang1314 2011-10-18  
必须收藏啊~
2 楼 liuxuejin 2011-01-19  
不错!谢谢啊!
1 楼 ren00317574 2010-08-09  
不错,谢谢了

相关推荐

    spring五种事务配置demo

    测试spring事务管理 搭建了ssh框架的web工程 本工程用到的数据库表很简单 user(id, name) 可自行创建 本例所有的事务放在service层进行管理,方法中间抛出运行时异常以测试是否回滚 Spring配置文件中关于事务...

    Spring + Hibernate + Struts 事务配置小例子(带提示框等小技巧)

    -- 事务拦截器bean需要依赖注入一个事务管理器 --> <!-- 下面定义事务传播属性 [ bus* 事务的方法名]--> *">PROPAGATION_REQUIRED <!-- 定义BeanNameAutoProxyCreator,该bean是个bean后...

    Spring事务配置5种方式

    DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问 时,DataSource实际为SessionFactory,TransactionManager的实现为 HibernateTransactionManager。

    Spring事务配置的五种方法

    DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用Hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager。

    Spring事务配置的五种方式

    Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。 DataSource、TransactionManager这两部分只是会...

    spring分别与jdbc和hibernate结合的事务控制--案例

    本案例主要是分别实现Spring与jdbc和hibernate结合的事务控制,如果该案例有出入的地方,请给我留言,我们一起交流

    SSH整合&&SSH集成开发

    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <!-- JTA环境的事务配置 WebLogicJtaTransactionManager"/> --> <!-- 使用annotation...

    SSH第7章上机.zip ACCP8.0

    -- 创建事务管理器(spring针对hibernate实现的事务管理的切面类) --> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <!-- 事务的通知类型 -...

    客户关系管理系统框架搭建(二)

    --4 创建事务管理器 aop切面--> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <!--5 配置处理事务的注解--> * 创建dao...

    Druid连接泄露问题重现&解决方式.pdf

    Druid连接泄露问题重现&解决方式

    Myeclipse6.0中SSH框架搭建

    -- 事务处理 --> class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> </bean> <!-- 其它Bean定义在此 --> <!...

    ssh框架在application.xml中配置数据源所需jar

    -- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> </property> <!-- 配置事务的传播特性 --> *" ...

    OA项目SSH整合框架

    -- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"></property> ...

    ssh(structs,spring,hibernate)框架中的上传下载

    Struts+Spring+Hibernate实现上传下载    本文将围绕SSH文件上传下载的主题,向您详细讲述如何开发基于SSH的Web程序。SSH各框架的均为当前最新版本:  •Struts 1.2  •Spring 1.2.5  •Hibernate 3.0 ...

    维生药业小项目 SSH简单学习项目

    class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <!-- 使用annotation定义事务 --> proxy-target-class="true" /> <!-- 使用annotation 自动注册bean,并检查@Required,@...

    spring3.2+strut2+hibernate4

    -- 事务配置管理 --> <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- ...

    spring 理解文件HibernateDaoSupport

    配置datasource-->sessionfacrtory from dataSource--->HibernateTransactionManager(impl)-->PROPAGATION_REQUIRED事物隔离级别 (2).不同点: HibernateDaoSupport: 在impl中要调用的方法要...

    springframework.5.0.12.RELEASE

    HibernateTransactionManager (unintentionally) bound to Hibernate 5.2 SharedSessionContractImplementor [SPR-17557] #22089 Spring JavaMailSenderImpl does not show proper message when recipient list is ...

    SpringMVC+Hibernate全注解整合

    class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <!-- Spring AOP config配置切点 --> (public * com.org.service.*.*(..))" id="bussinessService" /> <!-- 配置...

    SPRING API 2.0.CHM

    HibernateTransactionManager HiddenInputTag HierarchicalBeanFactory HierarchicalMessageSource HierarchicalThemeSource HotSwappableTargetSource HsqlMaxValueIncrementer HtmlCharacterEntityDecoder ...

Global site tag (gtag.js) - Google Analytics