Spring 是如何保证一个事务内获取同一个Connection

简介: Spring 是如何保证一个事务内获取同一个Connection

Spring 事务管理接口

640.png

  • DataSourceTransactionManager:适用于使用JDBC和iBatis进行数据持久化操作的情况,在定义时需要提供底层的数据源作为其属性,也就是 DataSource
  • HibernateTransactionManager:适用于使用Hibernate进行数据持久化操作的情况,与 HibernateTransactionManager 对应的是 SessionFactory
  • JpaTransactionManager:适用于使用JPA进行数据持久化操作的情况,与 JpaTransactionManager 对应的是 EntityManagerFactory


Spring 事务

Spring有声明式事务和编程式事务,声明式事务只需要提供 @Transactional的注解。然后事务的开启、提交、回滚、资源的清理都由Spring 来管理,开发人员只需要关心业务即可。

编程式事务需要使用 Spring的事务模板 TransactionTemplate或者使用直接使用底层的PlatformTransactionManager手动控制提交、回滚。


使用 TransactionTemplate 事务管理

public class SimpleService implements Service {
  // single TransactionTemplate shared amongst all methods in this instance
  private final TransactionTemplate transactionTemplate;
  // use constructor-injection to supply the PlatformTransactionManager
  public SimpleService(PlatformTransactionManager transactionManager) {
    Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null.");
    this.transactionTemplate = new TransactionTemplate(transactionManager);
  }
  public Object someServiceMethod() {
    return transactionTemplate.execute(new TransactionCallback() {
      // the code in this method executes in a transactional context
      public Object doInTransaction(TransactionStatus status) {
        updateOperation1();
        return resultOfUpdateOperation2();
      }
    });
  }
}


使用PlatFormTransactionManager 的例子

DefaultTransactionDefinition def = new DefaultTransactionDefinition();
// explicitly setting the transaction name is something that can only be done programmatically
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);
try {
  // execute your business logic here
}
catch (MyException ex) {
  txManager.rollback(status);
  throw ex;
}
txManager.commit(status);


Spring事务传播级别


  • Spring事务的传播级别描述的是多个使用了@Transactional注解的方法互相调用时,Spring对事务的处理。包涵的传播级别有:
  • REQUIRED, 如果当前线程已经在一个事务中,则加入该事务,否则新建一个事务。
  • SUPPORT, 如果当前线程已经在一个事务中,则加入该事务,否则不使用事务。
  • MANDATORY(强制的),如果当前线程已经在一个事务中,则加入该事务,否则抛出异常。
  • REQUIRES_NEW,无论如何都会创建一个新的事务,如果当前线程已经在一个事务中,则挂起当前事务,创建一个新的
  • NOT_SUPPORTED,如果当前线程在一个事务中,则挂起事
  • NEVER,如果当前线程在一个事务中则抛出异常。
  • NESTED, 执行一个嵌套事务,有点像REQUIRED,但是有些区别,在Mysql中是采用SAVEPOINT来实现的。



要注意的是 Spring 中的 Bean 都是无状态的单例,DAO ,Connection 是单例的,同一时刻不能被多个线程共享,否则可能有线程安全问题。


org.springframework.transaction.suport.TransactionSynchronizationManager

Spring 事务管理器通过  TransactionSynchronizationManager 来解决同一个事务中不同 DAO  获得的是同一个。


看代码吧:

事务管理器的 xml 配置 里面注入了数据源 datasource

<bean id="paymentTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
            abstract="false" lazy-init="default" autowire="default">
        <property name="dataSource">
            <ref bean="paymentDataSource" />
        </property>
    </bean>
    <tx:annotation-driven transaction-manager="paymentTransactionManager" />


Update 时是怎么获取 Connection 呢?

640.png

640.png


通过 TransactionSynchronizationManager  去取 Connection

事务管理器是怎么获得 Connection 呢

640.png

640.png

640.png


TransactionSynchronizationManager维护了ThreadLocal去取 Connection 其中 ThreadLocal 中的 key 是 datasource ,dataSource 是一致的,取到的Connection 就是一个


org.springframework.jdbc.datasource.DataSourceTransactionManager


事务回滚也一样


protected void doRollback(DefaultTransactionStatus status) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
        Connection con = txObject.getConnectionHolder().getConnection();
        if (status.isDebug()) {
            logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
        }
        try {
            con.rollback();
        }
        catch (SQLException ex) {
            throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
        }
    }



同一个连接执行不同的SQL语句 ,最后在同时rollback,或者 Comit 保证了是一个原子操作


@Override
    protected void doCommit(DefaultTransactionStatus status) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
        Connection con = txObject.getConnectionHolder().getConnection();
        if (status.isDebug()) {
            logger.debug("Committing JDBC transaction on Connection [" + con + "]");
        }
        try {
            con.commit();
        }
        catch (SQLException ex) {
            throw new TransactionSystemException("Could not commit JDBC transaction", ex);
        }
    }



相关文章
|
1月前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
2月前
|
Java 关系型数据库 MySQL
Spring 事务失效场景总结
Spring 事务失效场景总结
44 4
|
1月前
|
Java 程序员 数据库连接
女朋友不懂Spring事务原理,今天给她讲清楚了!
该文章讲述了如何解释Spring事务管理的基本原理,特别是针对女朋友在面试中遇到的问题。文章首先通过一个简单的例子引入了传统事务处理的方式,然后详细讨论了Spring事务管理的实现机制。
女朋友不懂Spring事务原理,今天给她讲清楚了!
|
1月前
|
XML Java 数据库
Spring5入门到实战------15、事务操作---概念--场景---声明式事务管理---事务参数--注解方式---xml方式
这篇文章是Spring5框架的实战教程,详细介绍了事务的概念、ACID特性、事务操作的场景,并通过实际的银行转账示例,演示了Spring框架中声明式事务管理的实现,包括使用注解和XML配置两种方式,以及如何配置事务参数来控制事务的行为。
Spring5入门到实战------15、事务操作---概念--场景---声明式事务管理---事务参数--注解方式---xml方式
|
1月前
|
前端开发 Java 数据库连接
一天十道Java面试题----第五天(spring的事务传播机制------>mybatis的优缺点)
这篇文章总结了Java面试中的十个问题,包括Spring事务传播机制、Spring事务失效条件、Bean自动装配方式、Spring、Spring MVC和Spring Boot的区别、Spring MVC的工作流程和主要组件、Spring Boot的自动配置原理和Starter概念、嵌入式服务器的使用原因,以及MyBatis的优缺点。
|
1月前
|
Java 关系型数据库 MySQL
Spring Boot事务配置管理
主要总结了 Spring Boot 中如何使用事务,只要使用 @Transactional 注解即可使用,非常简单方便。除此之外,重点总结了三个在实际项目中可能遇到的坑点,这非常有意义,因为事务这东西不出问题还好,出了问题比较难以排查,所以总结的这三点注意事项,希望能帮助到开发中的朋友。
|
2月前
|
Java 数据库连接 API
Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法
Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法
|
2月前
|
Java Spring
spring 事务控制 设置手动回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
spring 事务控制 设置手动回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
|
2月前
|
XML Java 关系型数据库
面试一口气说出Spring的声明式事务@Transactional注解的6种失效场景
面试一口气说出Spring的声明式事务@Transactional注解的6种失效场景
|
2月前
|
Java Spring
解析Spring Boot中的事务管理机制
解析Spring Boot中的事务管理机制