`

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_的编程式事务管理及声明式事务管理

    它通过实现 `PlatformTransactionManager` 接口的实例,如 `HibernateTransactionManager` 或 `DataSourceTransactionManager` 来进行事务管理。开发者可以在代码中调用 `TransactionTemplate` 或直接使用 `...

    spring3.0两种事务管理配置

    Spring 3.0 提供了两种事务管理配置方法:基于 XML 的事务管理和基于 @Transactional 的事务管理,这两种方法都是为了实现事务管理的目标,分别具有不同的配置方式和优缺点。 基于 XML 的事务管理 这种方法不需要...

    Xml文件配置实现声明式事务管理

    1. **配置事务管理器**:Spring支持多种事务管理器,如`DataSourceTransactionManager`(用于JDBC)、`HibernateTransactionManager`(用于Hibernate)等。例如,对于Hibernate,配置如下: ```xml ...

    spring hibernate 事务管理学习笔记(二)

    在本篇“Spring Hibernate 事务管理学习笔记(二)”中,我们将深入探讨Spring框架与Hibernate集成时如何实现高效、安全的事务管理。这是一篇关于源码分析和技术工具使用的文章,适合对Java开发和数据库操作有基础...

    Spring事务管理的三种方式

    Spring提供了PlatformTransactionManager接口,如DataSourceTransactionManager和HibernateTransactionManager,它们实现了事务管理的基本功能。开发者可以手动调用begin()开始事务,commit()提交事务,或者rollback...

    全面分析_Spring_的编程式事务管理及声明式事务管理.

    在Spring中,我们通常通过PlatformTransactionManager接口实现事务管理,如DataSourceTransactionManager(适用于JDBC)或HibernateTransactionManager(适用于Hibernate)。事务的开始通常用`transactionManager....

    JAVA(Spring)事务管理.doc

    在Java的Spring框架中,事务管理是至关重要的一个部分,特别是在多线程和并发环境下,保证数据的一致性和完整性。Spring提供了丰富的事务管理API来帮助开发者处理事务相关的操作。 首先,我们来看一下Spring事务...

    spring声明式事务管理配置方式

    - Spring支持多种事务管理器,如DataSourceTransactionManager(用于JDBC事务)和HibernateTransactionManager(用于Hibernate)。事务管理器是负责处理事务的核心组件,它根据配置决定如何开始、提交、回滚事务。 ...

    Spring事务管理的jar包

    在Spring中,事务管理器(如DataSourceTransactionManager或HibernateTransactionManager)是核心组件,它负责与底层数据库进行交互,执行事务的开始、提交、回滚等操作。开发者可以在XML配置文件中定义事务管理器,...

    注解实现声明式事务管理

    Spring提供了多种实现,如DataSourceTransactionManager(用于JDBC事务)和HibernateTransactionManager(用于Hibernate事务管理)。 接下来,我们关注注解。在Spring中,主要使用以下几种注解来实现声明式事务管理...

    spring_如何管理事务的

    - `HibernateTransactionManager`:针对Hibernate的事务管理。 - `JTATransactionManager`:用于Java Transaction API (JTA)环境下的事务管理。 ##### 2. 使用示例 ```java // 创建事务定义 ...

    Spring事务管理4种方式

    本文将详细介绍Spring事务管理的四种方式:编程式事务管理、声明式事务管理、PlatformTransactionManager接口以及TransactionTemplate。 1. **编程式事务管理**:这是一种手动控制事务的方式,通过在代码中调用`...

    Spring声明式事务配置管理方法

    Spring 声明式事务管理是Spring框架中的一个重要特性,它允许开发者在不编写任何事务管理代码的情况下,通过配置来管理事务。这种方式极大地简化了事务处理,并提高了代码的可维护性。以下是关于Spring声明式事务...

    基于java的企业级应用开发:Spring事务管理概述.ppt

    - `HibernateTransactionManager`:专为Hibernate ORM框架设计的事务管理器。 - `JtaTransactionManager`:支持全局事务管理(JTA)。 2. **TransactionDefinition**: TransactionDefinition接口定义了事务的...

    spring,hibernate整合实现事务管理(MethodInterceptor)

    - 创建事务管理器:通常我们会使用`HibernateTransactionManager`,它实现了`PlatformTransactionManager`,并知道如何与Hibernate的`Session`协同工作。 - 配置事务管理:在Spring的配置文件中,为事务管理器指定...

    spring hibernate 事务管理学习笔记(一)

    本文将深入探讨Spring与Hibernate整合时的事务管理,帮助你更好地理解和运用这些技术。 首先,Spring框架是Java企业级应用的基石,它提供了一种依赖注入(Dependency Injection,DI)的方式,使得组件之间的耦合度...

    spring mvc+hibernate实现事务管理(配置文件版)

    在本项目中,我们需要配置Spring的事务管理器,一般有两种方式:编程式事务管理和声明式事务管理。声明式事务管理更为常见,它通过在服务层的方法上添加@Transactional注解,由Spring自动进行事务的开启、提交或回滚...

    Spring事务管理的方法

    - `PlatformTransactionManager`:这是Spring提供的事务管理器接口,具体实现包括`DataSourceTransactionManager`(基于数据源的事务管理)、`HibernateTransactionManager`(基于Hibernate的事务管理)等。...

    09-4编程式事务管理.rar

    在Spring中,编程式事务管理通常使用PlatformTransactionManager接口实现,如DataSourceTransactionManager(适用于JDBC事务)或HibernateTransactionManager(适用于Hibernate)。通过这个接口,我们可以手动开启...

    spring3、 hibernate4 配置声明式事务管理(annotation方式)

    - `PlatformTransactionManager`:事务管理器接口,具体实现有`DataSourceTransactionManager`(适用于JDBC事务)和`HibernateTransactionManager`(适用于Hibernate事务)。 - `@Transactional`:用于标记事务...

Global site tag (gtag.js) - Google Analytics