美文网首页
详解Spring的事务管理PlatformTransaction

详解Spring的事务管理PlatformTransaction

作者: 名字是乱打的 | 来源:发表于2021-06-24 01:22 被阅读0次

常规的事务大致有许多种,比如jdbc事务, Hibernate的事务, JpaTransactionObject事务
关于他们的对比可以看看事务比较
我们直接看PlatformTransactionManager

Spring进行了统一的抽象,形成了PlatformTransactionManager事务管理器接口,事务的提交、回滚等操作全部交给它来实现。

Spring的事务体系也是在PlatformTransactionManager事务管理器接口上开展开来的(不管是JPA还是JDBC等都实现自接口 PlatformTransactionManager 如果你添加的是 spring-boot-starter-jdbc 依赖,框架会默认注入 DataSourceTransactionManager实例。如果你添加的是 spring-boot-starter-data-jpa 依赖,框架会默认注入 JpaTransactionManager 实例。,所以先来了解下PlatformTransactionManager事务管理器。

事务功能的总体接口设计

先来看下三大接口,三个接口功能一句话总的来说事务管理器基于事务基础信息在操作事务时候对事务状态进行更新。

  • PlatformTransactionManager : 事务管理器

  • TransactionDefinition : 事务的一些基础信息,如超时时间、隔离级别、传播属性等

  • TransactionStatus : 事务的一些状态信息,如是否是一个新的事务、是否已被标记为回滚

一. 看下PlatformTransactionManager如何来操作事务:

public interface PlatformTransactionManager {
 
    //根据事务定义TransactionDefinition,获取事务
    TransactionStatus getTransaction(TransactionDefinition definition);
 
    //提交事务
    void commit(TransactionStatus status);
 
    //回滚事务
    void rollback(TransactionStatus status);
}

二. 事务定义接口TransactionDefinition

  • 1.事务的定义包含:事务的隔离级别、事务的传播属性、超时时间设置、是否只读
    1. 红线上方是些常量定义,关于常量定义(事务的隔离级别和事务的传播属性等等) 具体事务常量定义
这里我们要明白的地方:

事务的隔离级别是数据库本身的事务功能,我们只是基于对数据库的Connection,对书屋操作做封装,而事务的传播属性则是Spring自己为我们提供的功能,数据库事务没有事务的传播属性这一说法。

DefaultTransactionDefinitio实现了该接口(TransactionDefinition):进行了一些默认的事务定义
public class DefaultTransactionDefinition implements TransactionDefinition, Serializable {
    private int propagationBehavior = PROPAGATION_REQUIRED;
    private int isolationLevel = ISOLATION_DEFAULT;
    private int timeout = TIMEOUT_DEFAULT;
    private boolean readOnly = false;
    //略
}
  • 事务的传播属性PROPAGATION_REQUIRED,如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。被设置成这个级别时,会为每一个被调用的方法创建一个逻辑事务域。如果前面的方法已经创建了事务,那么后面的方法支持当前的事务,如果当前没有事务会重新建立事务,其他请看事务的传播属性
  • 事务的隔离级别 采用底层数据库默认的隔离级别
  • 超时时间 采用底层数据库默认的超时时间
  • 是否只读为false

三. 事务的状态信息定义TransactionStatus

先引出Connection连接中的保存点功能:

//创建一个保存点
conn.setSavepoint(name);
//回滚到某个保存点
conn.rollback(savepoint);
//释放某个保存点
conn.releaseSavepoint(savepoint);

TransactionStatus它继承了SavepointManager接口,SavepointManager是对事务中上述保存点功能的封装,如下:

public interface SavepointManager {
    Object createSavepoint() throws TransactionException;
    void rollbackToSavepoint(Object savepoint) throws TransactionException;
    void releaseSavepoint(Object savepoint) throws TransactionException;
}

Spring利用保存点功能实现了事务的嵌套功能。后面会详细说明。

至于我们说的TransactionStatus本身更多存储的是事务的一些状态信息:

  • 是否是一个新的事物
  • 是否有保存点
  • 是否已被标记为回滚

常用的TransactionStatus接口实现为DefaultTransactionStatus,真正用来操作事务的

目前jdbc事务是通过Connection来实现事务的,Hibernate是通过它自己定义的Transaction来实现的,所以各家的事务都不同,所以

Spring只能以Object transaction的形式来表示各家的事务,事务的回滚和提交等操作都会最终委托给上Object transaction来完成。

Object transaction的职责就是提交回滚事务,这个transaction的选择可能如下:

  • DataSourceTransactionObject
  • HibernateTransactionObject
  • JpaTransactionObject(之后再详细说)

详细信息分别如下:

  • 对于DataSourceTransactionObject:
    我们使用了dataSource来获取连接,要想实现事务功能,必然需要使用Connection,所以它中肯定有一个Connection来执行事务的操作。
    DataSourceTransactionObject中有一个ConnectionHolder,它封装了一个Connection

  • 对于HibernateTransactionObject:
    我们使用了hibenrate,此时要想实现事务功能,必然需要通过hibernate自己定义的Transaction来实现。
    HibernateTransactionObject中含有一个SessionHolder,和上面的ConnectionHolder一样,它封装了一个Session,有了Session,我们就可以通过Session来产生一个Hibernate的Transaction,从而实现事务操作。

四. 事务管理器接口定义PlatformTransactionManager

类图关系如下:

重点来说下

  • AbstractPlatformTransactionManager
    • DataSourceTransactionManager
    • HibernateTransactionManager
    • JpaTransactionManager(之后详细再说)

这就需要来看看事务管理器的接口,上述的他们都是怎么实现的:

  • 1 第一个接口:TransactionStatus getTransaction(TransactionDefinition definition) 根据事务定义获取事务状态

    大体内容就是先获取上述说明的Object transaction,判断当前事务是否已存在,如果存在则进行事务的传播属性处理,后面详细说明,如果不存在new DefaultTransactionStatus,新创建一个事务,同时使用Object transaction开启事务。 分成了几个过程:

    不同的事务管理器获取不同的Object transaction

    • Spring获取Object transaction:
      DataSourceTransactionManager就是获取上述的DataSourceTransactionObject

    从当前线程中获取绑定的ConnectionHolder,可能为null,如果为null,则会在下一个开
    启事务的过程中,从dataSource中获取一个Connection,封装成ConnectionHolder,然后再绑定到当前线程

    然后我们new 一个DataSourceTransactionObject了,具体过程如下:

构建DefaultTransactionStatus,使用Object transaction开启事务

DataSourceTransactionManager的DataSourceTransactionObject开启过程如下:
首先判断之前的获取当前线程绑定的ConnectionHolder是否为null,如果为null,从dataSource中获取一个Connection,封装成ConnectionHolder,然后再绑定到当前线程(通过ThreadLocal来实现,可以看我别的文章)

因为开启了一个事务,则必须要关闭DataSourceTransactionObject中Connection的自动提交,代码如下(省略一些):

protected void doBegin(Object transaction, TransactionDefinition definition) {
        DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
        Connection con = null;
 
        //如果ConnectionHolder是否为null,从新获取
        if (txObject.getConnectionHolder() == null ||
                txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
            Connection newCon = this.dataSource.getConnection();
            txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
        }
        con = txObject.getConnectionHolder().getConnection();
 
        Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
        txObject.setPreviousIsolationLevel(previousIsolationLevel);
 
        //取消自动提交
        if (con.getAutoCommit()) {
            txObject.setMustRestoreAutoCommit(true);
            if (logger.isDebugEnabled()) {
                logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
            }
            con.setAutoCommit(false);
        }
        txObject.getConnectionHolder().setTransactionActive(true);
 
 
        //如果是新增的ConnectionHolder,则绑定到当前线程
        if (txObject.isNewConnectionHolder()) {
            TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
        }
    }

第二个接口:void rollback(TransactionStatus status) 回滚事务

回滚,则还是利用DefaultTransactionStatus内部的Object transaction来执行回滚操作

DataSourceTransactionManager就是使用DataSourceTransactionObject中的Connection来进行回滚操作

protected void doRollback(DefaultTransactionStatus status) {
    DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
    Connection con = txObject.getConnectionHolder().getConnection();
    try {
        con.rollback();
    }
    catch (SQLException ex) {
        throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
    }
}

第三个接口: void commit(TransactionStatus status) 提交事务

同理,DataSourceTransactionManager依托内部的Connection来完成提交操作

这里对于使用提供一个小demo

比如我们现在涉及到一个付款成功的业务,涉及到数据库金额更新和数据库订单状态数据更新,那么前端发送一个请求到我们的controller,我们在controller做向上反馈,在service做事务管理的业务操作以及数据库操作

@PostMapping("moneyOperation")
    public String moneyOperation() {
        if (transactionOperation.moneyOperation()) {
            return "付款成功";
        }
        else {
            return "付款失败!";
        }
    }
/**
 * @description: money相关事务demo
 * @author: zyh
 * @create: 2021-06-23 14:06
 **/
@Service
@Slf4j
@RequiredArgsConstructor
public class TransactionOperation {
    private final PlatformTransactionManager transactionManager;


    public boolean moneyOperation() {
        TransactionStatus status;
        // 手动开启事务初始化
        status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        //操作
        try {
            // 数据库操作后(例如业务上需先更新金额,再更新订单信息)
            moneyDaoOperation();
            DefaultTransactionDefinition
            // 操作无异常:提交事务
            transactionManager.commit(status);
            log.debug("操作xxxx成功");
            return true;
        } catch (Exception e) {
            log.debug("操作xxxx成功出错,正在回滚,错误信息为:"+e.getMessage());
            // 捕获异常, 事务回滚
            transactionManager.rollback(status);
            log.debug("操作xxxx已回滚");
            return false;
        }
    }
}

参考https://blog.csdn.net/luzhensmart/article/details/90167871
``

事务的失效场景

https://mp.weixin.qq.com/s/wrs5rUlFKdemU6m_QUYCZg

相关文章

  • 详解Spring的事务管理PlatformTransaction

    常规的事务大致有许多种,比如jdbc事务, Hibernate的事务, JpaTransactionObject事...

  • Spring之事务管理

    Spring事务管理(详解+实例)Spring详解(八)------事务管理 一. 概念 事务(Transacti...

  • 一文解析Spring编程式和声明式事务实例讲解

    接上一篇:一文解析Spring事务管理详解;通俗易懂,轻松掌握! Spring事务管理 Spring支持两种方式的...

  • Spring

    1.Spring事务的传播特性 2.Spring事务管理(详解+实例) 3.mem dump中unreachabl...

  • Index of contents

    一、事务 @TransactionalSpring事务传播行为详解Spring事务管理的两种方式try catch...

  • Spring中的AOP事务

    【目录】1 Spring的事务管理机制2 Spring事务管理两种方式 1 Spring的事务管理机制 Sprin...

  • Spring事务管理只对出现运行期异常进行回滚

    使用spring难免要用到spring的事务管理,要用事务管理又会很自然的选择声明式的事务管理,在spring的文...

  • spring事务

    1、spring事务管理器PlatformTransactionManager 1.1、没有spring事务管理器...

  • Spring-事务机制

    一、Spring事务 事务管理概述 Spring事务管理分为编程式事务管理和声明式事务管理两种 编程式事务:允许用...

  • Spring事务管理详解

    Spring事务介绍 Spring并不直接管理事务,而是提供了多种事务管理器,他们将事务管理的职责委托给Hiber...

网友评论

      本文标题:详解Spring的事务管理PlatformTransaction

      本文链接:https://www.haomeiwen.com/subject/tcjbyltx.html