代码编织梦想

一、Spring事务分类

  1. 编程式事务: 如果系统需要明确的事务,并且需要细粒度的控制各个事务的边界,此时建议使用编程式事务
  2. 声明式事务: 如果系统对于事务的控制粒度较为粗糙,则建议使用声明式事务,可以通过注解@Transational实现,原理是利用Spring框架通过AOP代理自动完成开启事务,提交事务,回滚事务。回滚的异常默认是运行时异常,可以通过rollbackFor属性制定回滚的异常类型。

二、Spring事务的三大接口

提示:通过Spring事务的源码可知,Spring不是直接管理事务的,而是提供了多种事务管理器,通过这些事务管理器,Spring将事务委托给了Hibernate、MyBaits、JTA等持久性框架的事务来实现

2.1 PlatformTransationManager接口
public interface PlatformTransactionManager extends TransactionManager {
    /**
    *  获取事务状态
    */
    TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
    /**
    *  提交事务
    */
    void commit(TransactionStatus var1) throws TransactionException;
    /**
    *  回滚事务
    */
    void rollback(TransactionStatus var1) throws TransactionException;
}
2.2 TransactionDefinition接口
public interface TransactionDefinition {
     /**
     *  支持当前事务,若当前没有事务就创建一个新的事务
     */
    int PROPAGATION_REQUIRED = 0;
    /**
     *  如果当前存在事务,则加入该事务,如果当前没有事务,则以非事务的方式继续运行
     */
    int PROPAGATION_SUPPORTS = 1;
    /**
     *  (强制性的)
     *  如果当前存在事务,则加入该事务,如果当前没有事务,则抛出异常
     */
    int PROPAGATION_MANDATORY = 2;
    /**
     *  创建一个新的事务,如果当前存在事务,则把当前事务挂起
     */
    int PROPAGATION_REQUIRES_NEW = 3;
    /**
     * 以非事务方式运行,如果当前存在事务,则把当前事务挂起
     */
    int PROPAGATION_NOT_SUPPORTED = 4;
    /**
     * 以非事务的方式运行,如果当前存在事务,则抛出异常
     */
    int PROPAGATION_NEVER = 5;
    /**
     * (嵌套的)
     * 表示如果当前正有一个事务在运行中,则该方法运行在一个嵌套的事务中,被嵌套的事务可以独立于封装的事务进行提交或者回滚(这里需要事务的保存点),如果封装的事务不存在,后续事务行为同PROPAGATION_REQUIRES_NEW
     */
    int PROPAGATION_NESTED = 6;
    /**
    *  使用后端的默认隔离级别
    */
    int ISOLATION_DEFAULT = -1;
   /**
    * 读未提交
    */
    int ISOLATION_READ_UNCOMMITTED = 1;
    /** 
    * 读已提交
    */
    int ISOLATION_READ_COMMITTED = 2;
    /**
    * 可重复度
    */
    int ISOLATION_REPEATABLE_READ = 4;
    /** 
    * 串行化
    */
    int ISOLATION_SERIALIZABLE = 8;
    int TIMEOUT_DEFAULT = -1;

    default int getPropagationBehavior() {
        return 0;
    }

    default int getIsolationLevel() {
        return -1;
    }

    default int getTimeout() {
        return -1;
    }

    default boolean isReadOnly() {
        return false;
    }

    @Nullable
    default String getName() {
        return null;
    }

    static TransactionDefinition withDefaults() {
        return StaticTransactionDefinition.INSTANCE;
    }
}

2.3 TransactionStatus接口
public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {
    /**
    *  是否有保存点
    */
    boolean hasSavepoint();
    /**
    *  将事务涉及的数据刷新到磁盘
    */
    void flush();
}

三、Spring事务嵌套最佳实践

我们将此方法作为内部方法,有外部方法调用此方法,我们在方法的最后面故意制造了算术异常来检验以下场景:

 /**
     * 项目延期
     *
     * @param id    工单id
     * @param value 延期天数
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, rollbackFor = Exception.class)
    public Boolean projectDelay(String id, Integer value) {
        EqOverhaulWorkOrderEntity eqOverhaulWorkOrderEntity = eqOverhaulWorkOrderMapper.selectById(id);
        Date startTime = eqOverhaulWorkOrderEntity.getStartTime();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startTime);
        calendar.add(Calendar.DAY_OF_MONTH, value);
        eqOverhaulWorkOrderEntity.setStartTime(calendar.getTime());
        int update = eqOverhaulWorkOrderMapper.updateById(eqOverhaulWorkOrderEntity);
        int i = 1/0;
        return update == 1;
    }
3.1 最佳实践场景一:

场景一为外部方法无事务注解,内部方法添加REQUIRED事务传播类型:
总结: 内部方法抛出异常,内部方法执行失败,不会影响外部方法的执行,外部方法执行成功。

3.2 最佳实践场景二:

场景二为外部方法添加REQUIRED事务传播类型,内部方法无事务注解。
总结: 内部方法抛出异常,会影响外部方法的执行,导致外部事务的回滚。

3.3 最佳实践场景三:

场景三为外部方法添加REQUIRED事务传播类型,内部方法添加REQUIRED事务传播类型。
总结: 内部方法抛出异常,会影响外部方法的执行,事务回滚。

3.4 最佳实践场景四:

场景四为外部方法添加REQUIRED事务传播类型,内部方法添加NOT_SUPPORTED事务传播类型。
总结: 内部方法抛出异常,外部方法回滚,内部方法不会回滚,外部方法抛出异常,内部方法执行成功,内部方法提交,内部方法抛出异常,也不会回滚。内部方法永远不会回滚。

3.5 最佳实践场景五:

场景五外部方法添加REQUIRED事务传播类型,内部方法添加REQUIRED_NEW事务传播类型。
总结:内部方法抛出异常,内部方法和外部方法都会执行失败,事务回滚。

3.6 最佳实践场景六:

场景六为外部方法添加REQUIRED事务传播类型,内部方法添加REQUIRED_NEW事务传播类型,并且把异常代码移动到外部方法的尾部。
总结: 外部方法抛出异常,外部方法执行失败,事务回滚,内部方法执行成功,内部方法事务提交。

3.7最佳实践场景七:

场景七为外部方法添加REQUIRED,内部方法添加REQUIRED_NEW事务传播类型,并且把异常代码移动到外部方法的尾部,同时外部方法和内部方法在同一个类中。
总结: 外部方法抛出异常, 内部方法和外部方法都会回滚。

四、Spring事务失效的场景

  1. 数据库不支持事务
  2. 事务方法未被Spring管理,也就是事务方法所在的类没有加载到Spring IOC容器中
  3. 方法没有被public修饰
    @Override
    @Transactional(rollbackFor = Exception.class)
    private Boolean projectDelay(String id, Integer value) {
        EqOverhaulWorkOrderEntity eqOverhaulWorkOrderEntity = eqOverhaulWorkOrderMapper.selectById(id);
        Date startTime = eqOverhaulWorkOrderEntity.getStartTime();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(startTime);
        calendar.add(Calendar.DAY_OF_MONTH, value);
        eqOverhaulWorkOrderEntity.setStartTime(calendar.getTime());
        int update = eqOverhaulWorkOrderMapper.updateById(eqOverhaulWorkOrderEntity);
        return update == 1;
    }

因为方法是私有的,加在私有方法上的事务注解不生效。
4. 在同一个类中的方法调用。
提示:举例详情见最佳实践场景七
5. 方法的事务传播类型不支持事务。
提示:举例详情见最佳实践场景四
6. 不正确地捕获异常。
使用了try-catch代码块将异常捕捉了,没有向上抛出异常,事务不会回滚。
7.标注错误的异常类型。
Spring事务默认回滚类型是RuntimeException类型,如果没有制定回滚的类型,抛出的错误不是RuntimeException类型,则无法回滚

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_54117624/article/details/124060850

spring 事务管理机制概述-爱代码爱编程

摘要:    一般地,用户的每次请求都对应一个业务逻辑方法,而一个业务逻辑方法往往包括一系列数据库原子访问操作,并且这些数据库原子访问操作应该绑定成一个事务来执行。然而,在使用传统的事务编程策略时,程序代码必然和具体的事务

spring事务实现过程及原理_兔子侠客的博客-爱代码爱编程_spring事务的实现方式和实现原理

1、Spring中事务处理的作用:   Spring事务处理,是将事务处理的工作统一起来,并为事务处理提供通用的支持。   2、工作原理及实现   a、划分处理单元——IOC   由于spring解决的问题是对单个数据库进行局部事务处理的,具体的实现首相用spring中的IOC划分了事务处理单元。并且将对事务的各种配置放到了ioc

spring事务控制--spring中的事务处理_robona的博客-爱代码爱编程_spring事务

事务回顾 1)什么是事务? 事务是逻辑上的一组操作,组成这组操作的各个逻辑单元,要么一起成功,要么一起失败。 2)事务的特性(ACID) 原子性(Atomicity):事务是一个原子操作,由一系列动作组成。事务的原

spring事务传播行为详解-爱代码爱编程

前言 Spring在TransactionDefinition接口中规定了7种类型的事务传播行为。事务传播行为是Spring框架独有的事务增强特性,他不属于的事务实际提供方数据库行为。这是Spring为我们提供的强大的工具箱,使用事务传播行可以为我们的开发工作提供许多便利。但是人们对他的误解也颇多,你一定也听过“service方法事务最好不要嵌套

spring事务(transactions)的原理与实现-爱代码爱编程

1、事务 1.1 什么是事务? 事务是用户定义的数据库操作的集合,这些操作作为一个完整的有机工作单元,要么全部正确执行,要么全部不执行。 四大特性: (1)原子性(atomicity)。一个事务是一个不可分割的工作单位,

Spring事务实现原理—Aop以及动态代理-爱代码爱编程

Spring事务实现原理—Aop以及动态代理 Spring事务管理机制的实现原理是由Spring内置的AOP——默认使用动态代理模式实现的。 AOP Spring的两大核心之一就是AOP,AOP:面向切面编程。在说原理之前,得先知道一些 AOP的专业术语。 AOP的专业术语 连接点(JoinPoint):增强执行的位置(增加代码的位置),Spring

基于SpringBoot的Spring事务实现原理-爱代码爱编程

基于SpringBoot的Spring事务实现原理 jar包版本 spring-boot-starter-web 2.1.3.RELEASE spring-aop 5.1.5.RELEASEspring-boot-starter-jdbc 2.1.3.RELEASE spring-jdbc 5.1.5.RELEASESpring事务概述

我所了解的Spring 事务原理-爱代码爱编程

一、事务的基本原理 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行: 获取连接 Connection con = DriverManager.getConnection()开启事务con.setAutoCommit(true/fals

Spring事务-爱代码爱编程

一、什么是事务 1.1 事务的概念 事务是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作;这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合(工作逻辑单元); 通俗的讲,就是为了达到某个目的,而做的一系列的操作,要么一起成功(事务提交),要么一起失败(事务回滚)。 最常见的例子就是转账:

MySQL深度解析--事务隔离级别-爱代码爱编程

MySQL事务隔离 Ⅰ.四种隔离级别 1.读未提交 一个事务还没提交时,它做的变更就能被别的事务看到。 2.读已提交 一个事务提交之后,它做的变更才会被其他事务看到。 3.可重复读 一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。 当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。 4.串行化 顾名思义是

Spring事务原理探究-爱代码爱编程

一、spring事务使用流程 1、使用spring提供的事务管理的时候,需要向容器中注入数据源 DataSource、注入事务管理器 PlatformTransactionManager,然后开启事务管理 @EnableTransactionManagement。 2、上面三步执行完毕之后,就可以在需要使用事务管理的类或者方法上使用 @Tran

Spring事务原理篇-爱代码爱编程

上一篇讲聊了一下Spring的事务使用,这一篇我们聊聊Spring的事务原理。 Spring的事务分为编程式事务以及声明式事务。声明式事务就是我们常用的@Transactional注解,关于该注解的使用,可以参考上一篇。说到事务,有经验的朋友就会想到事务的ACID属性,ACID属性是用来描述数据库的事务,Spring的事务和数据库的事务有什么关系呢?实际上

Spring事务管理的实现原理-爱代码爱编程

Spring事务管理的实现原理 文章目录 Spring事务管理的实现原理背景正文第一轮学习:总体分析,目标确认总体分析第二轮学习:正式进入源码,寻找突破口第二次分析总结第三轮学习:研究后续事务开启源码,完成整个过程第三次分析总结第四轮分析:根据实际应用,查漏补缺第四次分析总结 背景 首先,说明一下,这里指的Spring事务管理指的是spri