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:

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


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

相关推荐
SQL-First布道者5 分钟前
⚡ Spring JDBC 完整体系 · 第 5 讲 · Spring Boot Starter JDBC
java·spring boot·spring·mybatis·spring jdbc
宋哥转AI8 分钟前
深入理解 AI Agent · 多 Agent 编排 #03:Supervisor 与 Orchestrator——Dream-SaaS 双层编排架构拆解
java·人工智能·ai
木井巳12 分钟前
【JavaEE】Spring Web MVC 入门
java·spring boot·spring·servlet·java-ee
脚踏实地,坚持不懈!21 分钟前
Android ANR 内核底层全解析:从一次触摸到“应用无响应”
android·linux
2601_9621286423 分钟前
【JavaWeb06】Tomcat基础入门:架构理解与基本配置指南
java·架构·tomcat
要开心吖ZSH24 分钟前
腾讯 IM × TRTC 联动实战:后端如何撑起一次视频问诊(混流录制篇)
java·音视频·腾讯云·健康医疗·即时通讯·im
吴声子夜歌26 分钟前
Java——类、对象及方法(二)
java·开发语言
2401_8906034029 分钟前
Python入门语法(一)
java·开发语言·python
小蒜学长30 分钟前
springboot党建云课堂学习与管理系统(代码+数据库+LW)
java·数据库·spring boot·后端·学习
xhBruce41 分钟前
强制使用桌面模式 - SECONDARY_HOME -android-15.0.0_r23
android·launcher3