Spring Boot 事务和事务传播机制

这篇具有很好参考价值的文章主要介绍了Spring Boot 事务和事务传播机制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 为什么需要事务?

事务定义

将一组操作封装成一个执行单元 (封装到一起),这一组的执行具备原子性, 那么就要么全部成功,要么全部失败.

为什么要用事务?

比如转账分为两个操作:

第一步操作:A 账户-100 元。
第二步操作:B账户 +100 元。

如果没有事务,第一步执行成功了,第二步执行失败了,那么 A 账户平白无故的 100 元就“人间蒸发”了。而如果使用事务就可以解决这个问题,让这一组操作要么一起成功,要么一起失败。

2. Spring中事务的实现

Spring中的事务操作分为两类:

  1. 编程式事务(手动写代码操作事务)
  2. 声明式事务(利用注解自动开启和提交事务)

在开始讲解它们之前,咱们先来回顾事务在MSQL 中是如何使用的?

2.1 MySQL中的事务使用

事务在 MySQL 有 3个重要的操作: 开启事务、提交事务、回滚事务,它们对应的操作命令如下:

-- 开启事务
start transaction;
-- 业务执行

-- 提交事务
commit;

-- 回滚事务
rollback;

2.2 Spring 编程式事务(手动)

Spring 手动操作事务和上面MySQL 操作事务类似,它也是有3个重要操作步骤:

  • 开启事务(获取事务)
  • 提交事务
  • 回滚事务

SpringBoot 内置了两个对象,DataSourceTransactionManager 用来获取事务(开启事务)、提交或回滚事务的,而 TransactionDefinition 是事务的属性,在获取事务的时候需要将TransactionDefinition 传递进去从而获得一个事务 TransactionStatus,实现代码如下:

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    // 编程式事务
    // JDBC 事务管理器
    @Autowired
    private DataSourceTransactionManager transactionManager;
    // 定义事务属性 (使用TransactionDefinition记录事务属性)
    @Autowired
    private TransactionDefinition transactionDefinition;

    @RequestMapping("/del")
    public int del(Integer id) {
        if (id == null || id <= 0) return 0;
        // 1. 开启事务
        TransactionStatus transactionStatus = null;
        int result = 0;
        try {
            transactionStatus = transactionManager.getTransaction(transactionDefinition);
            // 业务操作: 删除用户
            result = userService.del(id);
            System.out.println("删除: " + result);
            // 2. 提交事务 / 回滚事务
//            transactionManager.commit(transactionStatus); // 提交事务
        } catch (Exception e) {
            if (transactionStatus != null) {
                transactionManager.rollback(transactionStatus); // 回滚事务
            }
        }
        return result;
    }
}

业务操作相关代码如下:

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    public int del(Integer id){
        return userMapper.del(id);
    }
}
@Mapper
public interface UserMapper {
    int del(@Param("id") Integer id);
}
    <delete id="del">
        delete from userinfo where id=#{id}
    </delete>

运行结果:

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

可以看到, 删除的业务操作已经成功了, 但是因为回滚操作, 所以在执行前后查询数据库的时候是可以看到对应的数据依然存在.

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

从上述代码可以看出,以上代码虽然可以实现事务,但操作也很繁琐,有没有更简单的实现方法呢?请看下面声明式事务。

2.3 Spring 声明式事务 (自动)

声明式事务的实现很简单,只需要在需要的方法上添加 @Transactional 注解就可以实现了,无需手动开启事务和提交事务,进入方法时自动开启事务,方法执行完会自动提交事务,如果中途发生了没有处理的异常会自动回滚事务,具体实现代码如下:

@RestController
@RequestMapping("/user2")
public class UserController2 {

    @Autowired
    private UserService userService;

    @Transactional  // 在方法开始之前开启事务, 方法正常执行结束之后提交事务, 如果执行途中发生异常, 则回滚事务.
    @RequestMapping("/del")
    public int del(Integer id) {
        if (id == null || id <= 0) return 0;
        return userService.del(id);
    }
}                  

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

执行前后查询数据库, 可以看到由于正常执行所以没有触发回滚.

2.3.1 @Transactional作用范围

@Transactional 可以用来修饰方法或类

  • 修饰方法时:需要注意只能应用到 public 方法上,否则不生效。推荐此种用法
  • 修饰类时:表明该注解对该类中所有的 public 方法都生效。

2.3.2 @Transactional 参数说明

参数

作用

value

当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器

transactionManager

当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器

propagation

事务的传播行为,默认值为 Propagation.REQUIRED

isolation

事务的隔离级别.默认值为 Isolation.DEFAULT

timeout

事务的超时时间,默认值为-1. 如果超过该时间限制但事务还没有完成,则自动回滚事务.

readOnly

指定事务是否为只读事务.默认值为 false;

为了忽略那些不需要事务的方法,比如读取数据可以设置read-only为 true.

rollbackFor

用于指定能够触发事务回滚的异常类型,可以指定多个异常类型

rollbackForClassName

用于指定能够触发事务回滚的异常类型,可以指定多个异常类型

noRollbackFor

抛出指定的异常类型,不回滚事务,也可以指定多个异常类型

noRollbackForClassName

抛出指定的异常类型,不回滚事务,也可以指定多个异常类型

2.3.3 注意事项

@Transactional 在异常被捕获的情况下,不会进行事务自动回滚,验证以下代码是否会发生事务回滚:

@RestController
@RequestMapping("/user2")
public class UserController2 {
    @Autowired
    private UserService userService;

    @Transactional 
    @RequestMapping("/del")
    public int del(Integer id) {
        if (id == null || id <= 0) return 0;
        int result = userService.del(id);
        System.out.println("删除: " + result);
        try {
            int num = 10 / 0;
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        return result;
    }
}                  

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

执行前后查询数据库, 可以看到在异常被捕获的情况下,并不会进行事务自动回滚.

事务不会自动回滚解决方案
解决方案1

对于捕获的异常,事务是会自动回滚的,因此解决方案1就是可以将异常重新抛出,具体实现如下:

@RestController
@RequestMapping("/user2")
public class UserController2 {
    @Autowired
    private UserService userService;

    @Transactional 
    @RequestMapping("/del")
    public int del(Integer id) {
        if (id == null || id <= 0) return 0;
        int result = userService.del(id);
        System.out.println("删除: " + result);
        try {
            int num = 10 / 0;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            throw e;
        }
        return result;
    }
}                  

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

执行前后查询数据库, 可以看到这里是有异常, 触发了回滚.

解决方案2

手动回滚事务,在方法中使用 TransactionAspectSupport.currentTransactionStatus() 可以得到当前的事务,然后设置回滚方法 setRollbackOnly 就可以实现回滚了,具体实现代码如下:

public class UserController2 {
        // .. 省略代码, 同上
        try {
            int num = 10 / 0;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            // 手动回滚事务
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return result;
    }
}                  

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

执行前后访问数据库可以看到, 这里成功实现了回滚操作.

2.3.4 @Transactional 工作原理

@Transactional 是基于 AOP 实现的,AOP 又是使用动态代理实现的。如果目标对象实现了接口,默认情况下会采用JDK 的动态代理,如果目标对象没有实现了接口,会使用CGLIB 动态代理。

@Transactional 在开始执行业务之前,通过代理先开启事务,在执行成功之后再提交事务。如果中途遇到的异常,则回滚事务。

@Transactional 实现思路预览:

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

@Transactional 具体执行细节如下图所示:

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

3. 事务隔离级别

3.1 事务特性回顾

事务有4 大特性 (ACID),原子性、持久性、一致性和隔离性,具体概念如下:

  • 原子性: 一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚 (Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
  • 一致性: 在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
  • 持久性: 事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
  • 隔离性: 数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交 (Read uncommitted)、读提交 (read committed) 、可重复读 (repeatable read) 和串行化(Serializable)。

上面 4个属性,可以简称为ACID

原子性 (Atomicity,或称不可分割性)
一致性 (Consistency)
隔离性 (lsolation,又称独立性)
持久性 (Durability)

而这 4 种特性中,只有隔离性 (隔离级别) 是可以设置的

为什么要设置事务的隔离级别?

设置事务的隔离级别是用来保障多个并发事务执行更可控,更符合操作者预期的。

什么是可控呢?

比如近几年比较严重的新冠病毒,我们会把直接接触到确诊病例的人员隔离到酒店,而把间接接触者 (和直接接触着但未确诊的人) 隔离在自己的家中,也就是针对不同的人群,采取不同的隔离级别,这种隔离方式就和事务的隔离级别类似,都是采取某种行动让某个事件变的“更可控”。而事务的隔离级别就是为了防止,其他的事务影响当前事务执行的一种策略

3.2 Spring 中设置事务隔离级别

Spring 中事务隔离级别可以通过 @Transactional 中的 isolation 属性进行设置,具体操作如下图所示:

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

3.2.1 MySQL事务隔离级别有 4 种

  1. READ UNCOMMITTED: 读未提交,也叫未提交读,该隔离级别的事务可以看到其他事务中未提交的数据。该隔离级别因为可以读取到其他事务中未提交的数据,而未提交的数据可能会发生回滚,因此我们把该级别读取到的数据称之为脏数据,把这个问题称之为脏读。
  2. READ COMMITTED: 读已提交,也叫提交读,该隔离级别的事务能读取到已经提交事务的数据,因此它不会有脏读问题。但由于在事务的执行中可以读取到其他事务提交的结果,所以在不同时间的相同 SQL查询中,可能会得到不同的结果,这种现象叫做不可重复读。
  3. REPEATABLE READ: 可重复读,是MySQL的默认事务隔离级别,它能确保同一事务多次查询的结果一致。但也会有新的问题,比如此级别的事务正在执行时,另一个事务成功的插入了某条数据,但因为它每次查询的结果都是一样的,所以会导致查询不到这条数据,自己重复插入时又失败(因为唯一约束的原因)。明明在事务中查询不到这条信息,但自己就是插入不进去,这就叫幻读(Phantom Read)
  4. SERIALIZABLE: 序列化,事务最高隔离级别,它会强制事务排序,使之不会发生冲突,从而解决了脏读、不可重复读和幻读问题,但因为执行效率低,所以真正使用的场景并不多

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

1. 脏读: 一个事务读取到了另一个事务修改的数据之后,后一个事务又进行了回滚操作,从而导致第一个事务读取的数据是错误的。
2. 不可重复读: 一个事务两次查询得到的结果不同,因为在两次查询中间,有另一个事务把数据修改了。
3. 幻读: 一个事务两次查询中得到的结果集不同,因为在两次查询中另一个事务有新增了一部分数据。

在数据库中通过以下SQL 查询全局事务隔离级别和当前连接的事务隔离级别:

select @@global.tx_isolation,@@tx_isolation;

以上SQL的执行结果如下:

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

3.2.2 Spring 中事务隔离级别有 5 种

Spring 中事务隔离级别包含以下 5 种:

  1. Isolation.DEFAULT: 以连接的数据库的事务隔离级别为主
  2. lsolation.READ_UNCOMMITTED: 读未提交,可以读取到未提交的事务,存在脏读
  3. Isolation.READ_COMMITTED: 读已提交,只能读取到已经提交的事务,解决了脏读,存在不可重复读。
  4. Isolation.REPEATABLE_READ: 可重复读,解决了不可重复读,但存在幻读(MVSQL默认级
  5. lsolation.SERIALIZABLE: 串行化,可以解决所有并发问题,但性能太低。

从上述介绍可以看出,相比于 MySQL 的事务隔离级别,Spring 的事务隔离级别只是多了一个lsolation.DEFAULT (以数据库的全局事务隔离级别为主)

Spring 中事务隔离级别只需要设置 @Transactional 里的 isolation 属性即可,具体实现代码如下:

@RequestMapping("/save")
@Transactional(isolation = Isolation.SERIALIZABLE)
public Object save(User user) {
    // 业务实现
}

4. Spring 事务传播机制

4.1 事务传播机制是什么?

Spring 事务传播机制定义了多个包含了事务的方法,相互调用时,事务是如何在这些方法间进行传递的。

4.2 为什么需要事务传播机制?

事务隔离级别是保证多个并发事务执行的可控性的(稳定性的),而事务传播机制是保证一个事务在多个调用方法间的可控性的 (稳定性的)。

例子: 像新冠病毒一样,它有不同的隔离方式(酒店隔离还是居家隔离),是为了保证疫情可控,然而在每个人的隔离过程中,会有很多个执行的环节,比如酒店隔离,需要负责人员运送、物品运送消杀原生活区域、定时核算检查和定时送餐等很多环节,而事务传播机制就是保证一个事务在传递过程中是可靠性的,回到本身案例中就是保证每个人在隔离的过程中可控的。

事务隔离级别解决的是多个事务同时调用一个数据库的问题,如下图所示:

而事务传播机制解决的是一个事务在多个节点(方法) 中传递的问题,如下图所示:

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

4.3 事务传播机制有哪些?

Spring 事务传播机制包含以下 7种:

  1. Propagation.REQUIRED: 默认的事务传播级别,它表示如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  2. Propagation.SUPPORTS: 如果当前存在事务,则加入该事务; 如果当前没有事务,则以非事务的方式继续运行。
  3. Propagation.MANDATORY: (mandatory: 强制性) 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
  4. Propagation.REQUIRES_NEW: 表示创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。
  5. Propagation.NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  6. Propagation.NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常
  7. Propagation.NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED。

以上 7 种传播行为,可以根据是否支持当前事务分为以下 3类:

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

以情侣关系为例来理解以上分类:

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

4.4 Spring 事务传播机制使用和各种场景演示

4.4.1 支持当前事务(REQUIRED)

我们有多个方法进行数据的传递.

不考虑拦截器, 考虑标准的分层, 比如要执行用户User的添加add操作, 下图为该执行流程图

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

首先要执行add, 就会先在UserController加@Transactional, 下面为了演示事务的传播机制, 就需要让用户调用UserService, 并加上@Transactional.
在UserService中, 我们需要操作两张表, 先调用UserMapper中的add添加方法, 这个方法是添加用户的, 再调用日志添加类.

从上图可见, @Transactional是通过UserController传递到UserService, 再从UserService传递到LogService.

注意, 正常来说在*Service要调用*Mapper类, 但是这里如果使用LogMapper是Interface, 就无法演示清楚预期效果, 所以这里调用LogService.

在mycnblog中创建日志表.

CREATE TABLE `log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `message` text COLLATE utf8mb4_unicode_ci NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

在项目中创建实体类:

@Data
public class UserInfo {
    private int id;
    private String username;
    private String password;
    private String photo;
    private LocalDateTime createtime;
    private LocalDateTime updatetime;
    private int state;
}
@Data
public class Log {
    private int id;
    private LocalDateTime timestamp;
    private String message;
}

演示事务传播机制代码实现:

User
@RestController
@RequestMapping("/user3")
public class UserController3 {

    @Autowired
    private UserService userService;

    @RequestMapping("/add")
    @Transactional(propagation = Propagation.REQUIRED)
    public int add(String username, String password){
        if (null == username || null == password ||
                username.equals("") || password.equals("")) return 0;
        UserInfo user = new UserInfo();
        user.setUsername(username);
        user.setPassword(password);
        int result = userService.add(user);
        // 用户添加操作
        return 0;
    }
}

UserService 实现代码如下:

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private LogService logService;

    @Transactional(propagation = Propagation.REQUIRED)
    public int add(UserInfo userInfo) {
        // 给用户表添加用户信息
        int addUserResult = userMapper.add(userInfo);
        System.out.println("添加用户结果: " + addUserResult);
        // 添加日志信息
        Log log = new Log();
        log.setMessage("添加用户信息"); 
        logService.add(log);
        return addUserResult;
    }
}

在UserMapper中写添加add方法.

@Mapper
public interface UserMapper {
    int add(UserInfo userInfo);
}

在xml中写具体的实现:

    <insert id="add">
        insert into userinfo(username, password) values
        (#{username},#{password})
    </insert>
Log

LogMapper.interface

@Mapper
public interface LogMapper {
    int add(Log log);
}

LogMapper.xml

    <insert id="add">
        insert into log(`message`) values(#{message})
    </insert>

LogService:

@Service
public class LogService {
    @Autowired
    private LogMapper logMapper;

    @Transactional(propagation = Propagation.REQUIRED)
    public int add(Log log) {
        int result = logMapper.add(log);
        System.out.println("添加日志结果: " + result);
        // 回滚操作
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        int num = 10 / 0;
        return result;
    }
}

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

接下来我们观察一下在UserService中已经执行成功的user添加操作有没有回滚事务, 如果user中没有正常添加数据, 那么就说明REQUIRED是支持当前的事务, 并且是以加入的方式去进行的.

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

可以看到, 添加用户和添加日志都已经成功了, 最终有一个算数异常报出. 我们再来看一下数据库.

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

可以看到, log回滚了, 符合预期, 然而userinfo中并没有将前面url所传数据wangwu添加过来, 那么这就说明, REQUIRED这种事务传播机制是支持当前事务的, 并且是加入事务的方式, 让自己变成事务的一部分, 如果其中有任何一个地方出现问题, 不论前面做了多少业务, 那么整条调用链上所有的方法都会进行回滚.

4.4.2 不支持当前事务(REQUIRESNEW)

将整条事务调用链上的所有方法修改为 REQUIRES_NEW不支持当前事务,重新创建事务,观察执行结果:

    @Transactional(propagation = Propagation.REQUIRES_NEW)

预期执行结果: 在一个调用链上的事务,各自执行相互不干扰。

对上面的示例来说, 是用户添加 (事务) 成功、但是日志添加 (事务) 失败。

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

可以看到, 我们的执行结果并没有符合我们的预计结果.

原因是由于没有处理 by zero的异常, 导致整个调用链上的其他对象都感知到了, 所以进行了回滚.

此时修改LogService代码:

@Service
public class LogService {
    @Autowired
    private LogMapper logMapper;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int add(Log log) {
        int result = logMapper.add(log);
        System.out.println("添加日志结果: " + result);
        // 回滚操作
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        return result;
    }
}

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

这个时候便不会报错了.

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

可以看到, 用户和日志都添加成功了, 但是日志中进行了手动回滚.

验证一下:

Spring Boot 事务和事务传播机制,JavaEE,java,mybatis,spring boot,后端,sql,mysql

说明符合了预期.


4.4.3 嵌套事务 (NESTED) 和加入事务 (REQUIRED )的区别

  • 整个事务如果全部执行成功,二者的结果是一样的。
  • 如果事务执行到一半失败了,那么加入事务整个事务会全部回滚;而嵌套事务会局部回滚,不会影响上一个方法中执行的结果

至此, 整个JavaEE专栏的知识介绍就到这里.文章来源地址https://www.toymoban.com/news/detail-667754.html

到了这里,关于Spring Boot 事务和事务传播机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring—事务及事务的传播机制

    将一组操作封装成一个执行单元, 即这一组操作一同成功 / 一同失败 举个栗子🌰 未使用事务 滑稽老哥给女神转账 520 由于某种原因, 女神并未收到转账的 520, 而滑稽老哥却被扣款 520 使用事务 滑稽老哥给女神转账 520 由于某种原因, 女神并未收到转账的 520 因为使用事务, 所以

    2024年02月13日
    浏览(44)
  • Spring事务和事务传播机制(1)

    ❤️❤️❤️SSM专栏更新中,各位大佬觉得写得不错,支持一下,感谢了!❤️❤️❤️ Spring + Spring MVC + MyBatis_冷兮雪的博客-CSDN博客 在Spring框架中,事务管理是一种用于维护数据库操作的一致性和完整性的机制。Spring事务管理提供了灵活的方式来处理事务,包括事务的创建

    2024年02月12日
    浏览(38)
  • Spring事务传播机制

    编程式事务管理:通过  TransactionTemplate 或者 TransactionManager 手动管理事务,实际应用中很少使用,这不是本文的重点,就不在这里赘述。 声明式事务管理:使用场景最多,也是最推荐使用的方式,直接加上@Transactional注解即可。 @Transactional 注解是用于声明事务性方法的注解

    2024年01月16日
    浏览(39)
  • Spring事务传播机制解析

    在Java的Spring框架中,事务管理是保证应用数据一致性和可靠性的关键。Spring提供了灵活的事务传播机制,它定义了事务边界,以及在嵌套方法调用时如何处理事务。本文旨在深入探讨Spring的事务传播行为,帮助开发者更好地理解和运用这一重要特性。 事务传播机制指的是在

    2024年01月16日
    浏览(39)
  • spring的事务传播机制

    嫌弃内容代码复杂的可直接看思维导图大纲即可 指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行 默认,当前存在事务,则加入该事务;不存在事务,创建新事务。 始终以新的事务运行,当前存在事务,则挂起原事务;不存在事务,创建新事务

    2023年04月23日
    浏览(53)
  • 【Spring】深入理解 Spring 事务及其传播机制

    在 Spring 框架中,事务(Transaction)是一种用于管理数据库操作的机制,旨在 确保数据的 一致性、可靠性和完整性 。事务可以将一组数据库操作(如插入、更新、删除等)视为一个单独的执行单元,要么 全部成功地执行,要么全部回滚 。这样可以确保数据库在任何时候都保

    2024年02月12日
    浏览(61)
  • Spring事务的四大特性+事务的传播机制+隔离机制

    原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 事务是一个原子操作, 由一系列动作组成。 组成一个事务的多个数据库操作是一个不可分割的原子单元 ,只有所有的操作执行成功,整个事务才提交。 事务中的任何一个数据库操作失败

    2024年01月20日
    浏览(40)
  • 一文详解Spring事务传播机制

    目录 背景 Spring事务 @Transactional注解 使用场景 失效场景 原理 常用参数 注意 事务传播机制 处理嵌套事务流程 主事务为REQUIRED子事务为REQUIRED 主事务为REQUIRED子事务为REQUIRES_NEW 主事务为REQUIRED子事务为NESTED 实现方式 源码解析 我们在使用Spring管理数据库事务的时候很方便,只

    2023年04月26日
    浏览(48)
  • Spring事务传播的7种机制

    1. Propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加入该事务;如果 当前没有事务,则创建一个新的事务。 2. Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的 方式继续运行。 3. Propagation.MANDATORY:(mandatory:强制

    2024年02月09日
    浏览(47)
  • Spring @Transactional事务传播机制详解

    我们日常工作中极少使用事务传播级别,单纯只是使用事务和rollbackfor抛出异常来解决事务问题,但其实我们很多时候使用的是不正确的,或者说会造成事务粒度过大,本文详解一下事务传播级别,也让自己更好地处理事务问题。 1.什么是事务传播机制? 举个栗子,方法A是一

    2024年02月14日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包