Spring事务的传播机制

目录

Spring 中事务的实现

编程式事务(了解即可):

编程式事务需要自己手动写代码操作事务


这里用用户注册来进行演示:


Spring ⼿动操作事务和上⾯ MySQL 操作事务类似, 有 3 个重要操作步骤:
• 开启事务(获取事务)
• 提交事务
• 回滚事务

java 复制代码
package com.suli.springtransdemo.Controller;

import com.suli.springtransdemo.Service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
public class UserController {
    @Autowired
    private UserService userService;

    // JDBC 事务管理器
    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;

    //定义事务的属性
    @Autowired
    private TransactionDefinition definition;

    @RequestMapping("registry")
    public String registry(String name, String password){
        /**
         * 1. 开启事务
         * 2. 数据操作
         * 3. 事务提交/回滚
         */

        //1. 开启事务
        TransactionStatus transaction = dataSourceTransactionManager.getTransaction(definition);

        //用户注册
        userService.registryUser(name,password);
        log.info("用户注册成功");

        //事务提交
//        dataSourceTransactionManager.commit(transaction);

        //事务回滚
        dataSourceTransactionManager.rollback(transaction);

        return "注册成功";
    }
}

声明式事务(利用注解自动开启和提交事务):

1.首先要添加依赖:

xml 复制代码
<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-tx</artifactId>
</dependency>

2.要使用@Transactional注解,无需手动开启事务和提交事
务, 进入方法时自动开启事务, 方法执行完会自动提交事务,如果中途发生了没有处理的异常会自动
回滚事务.

java 复制代码
@Slf4j
@RestController
public class UserController2 {
    @Autowired
    private UserService userService;

    @Autowired
    private LogInfoService logInfoService;

    @Transactional
    @RequestMapping("registry1")
    public String registry1(String name, String password){
        //用户注册
        Integer result = userService.registryUser(name,password);
        log.info("用户注册成功,影响行数"+ result);

        return "注册成功";
    }
}

事务回滚注意事项:

如果程序发生Error和IoException和RuntimeException这几个异常时,事务是不会自动进行回滚的

java 复制代码
/**
     * 抛出,RuntimeException不会自动回滚
     * @param name
     * @param password
     * @return
     */
    @Transactional
    @RequestMapping("registry2")
    public String registry(String name, String password){

        //用户注册
        Integer result = userService.registryUser(name,password);
        log.info("用户注册成功,影响行数"+ result);

        try {
            int a = 10/0;
        }catch (Exception e){
            log.error("程序发生异常");
            throw  new RuntimeException(e);

            //手动回滚
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }

        return "注册成功";
    }


    /**
     * 抛出IOException异常,事务没有自动进行回滚
     * @param name
     * @param password
     * @return
     */
    @Transactional
    @RequestMapping("registry3")
    public String registry3(String name, String password) throws IOException {

        //用户注册
        Integer result = userService.registryUser(name,password);
        log.info("用户注册成功,影响行数"+ result);

        try {
            int a = 10/0;
        }catch (Exception e){
            log.error("程序发生异常");
            throw  new IOException(e);

        }

        return "注册成功";
    }

结果观察:



看数据库:

Spring 事务传播机制:

Spring的事务的隔离级别和Mysql还是一样的,由于Mysql上没有方法调来调去,但是我们编程时会有方法上的调用可以不同方法没有用同一个事务会有嵌套等等情况,所以我们的事务还有传播机制!


事务主要有7中传播机制,接下来比较重要的我会用代码来解释一下


我会用一个Controller调用两个service里的方法来进行说明

1.Propagation.REQUIRED:

默认的事务传播级别,如果存在一个事务我们就用这个事务,如果没有事务就创建一个事务,大家一起用




先看没有异常的情况:
请求:


结果两个表都已提交,就是用同一个事务


发生异常:全部失败

7.Propagation.NESTED:

如果当前存在事务则创建新事务作为嵌套事务来运行,如果不存在事务则等价于Propagation.REQUIRED


没有异常情况:


结果:和情况一一样都得到提交

Propagation.NESTED和1.Propagation.REQUIRED的区别:

Propagation.NESTED的事务之间是父子关系,子事务发生异常会影响父事务,而Propagation.REQUIRED则不是


Propagation.NESTED情况下,当子事务发生异常,然后处理了(手动回滚事务)后就不会影响父事务和其他子事务:



结果发生异常的事务没有提交,但是没有发生异常的事务得到提交!

4.Propagation.REQUIRES_NEW:

如果当前存在有事务,就把这个事务挂起不用,自己创建新事务,事务之间相互独立,互不干扰




结果:事务之间互不影响,一个事务提交成功,一个失败

6.Propagation.NEVER:

以非事务的方式运行,如果当前存在事务则抛出异常


结果:直接抛出异常,自然两个都没有提交

相关推荐
GJCTYU10 分钟前
spring中@Transactional注解和事务的实战理解附代码
数据库·spring boot·后端·spring·oracle·mybatis
艾迪的技术之路20 分钟前
redisson使用lock导致死锁问题
java·后端·面试
mmoyula22 分钟前
【RK3568 驱动开发:实现一个最基础的网络设备】
android·linux·驱动开发
今天背单词了吗98038 分钟前
算法学习笔记:8.Bellman-Ford 算法——从原理到实战,涵盖 LeetCode 与考研 408 例题
java·开发语言·后端·算法·最短路径问题
天天摸鱼的java工程师41 分钟前
使用 Spring Boot 整合高德地图实现路线规划功能
java·后端
东阳马生架构1 小时前
订单初版—2.生单链路中的技术问题说明文档
java
sam.li1 小时前
WebView安全实现(一)
android·安全·webview
咖啡啡不加糖1 小时前
暴力破解漏洞与命令执行漏洞
java·后端·web安全
风象南1 小时前
SpringBoot敏感配置项加密与解密实战
java·spring boot·后端