spring的@Transactional事务原理理解

news2025/1/5 20:45:32

目录

    • @Transactional 普通例子代码和测试输出
    • 编程式事务
    • 事务代理实现和TransactionAspectSupport重要类
    • 复习Spring的事务传播机制有哪些
    • 实际工作中用到的事务处理

@Transactional事务原理理解

@Transactional 普通例子代码和测试输出

@Transactional(rollbackFor = Exception.class)
@PutMapping(value = "/test/oom")
public Boolean testOom() throws Exception {
    TbUser tbUser = new TbUser();
    tbUser.setUserid("abc");
    tbUser.setPassword("123456");
    tbUser.setName("abc");
    tbUser.setPhone("abc");
    tbUser.setAddress("abc");

    try {
        List<TbUser> tbUserList = tbUserService.getAllUser();
        System.out.println("users size1:" + tbUserList.size());
        tbUserService.insert(tbUser);
        tbUserList = tbUserService.getAllUser();
        System.out.println("users size2:" + tbUserList.size());
        // 继续业务处理,模拟异常
        int c = 1 / 0;
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    } finally {
        System.out.println("finally delete");
    }
}

测试输出如下
在这里插入图片描述
数据库去查询确实会滚了

编程式事务

如下为一种写法,事务的提交和会滚自己控制,借助spring的PlatformTransactionManager

   @Autowired
    private PlatformTransactionManager platformTransactionManager;

    @Autowired
    private JdbcTemplate jdbcTemplate;


    @PutMapping(value = "/test/transaction")
    public Boolean testTransaction() throws Exception {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus transactionStatus = platformTransactionManager.getTransaction(def);
        try {
            // 处理业务
            jdbcTemplate.update("insert into tb_user (name, phone, address) values (?, ?, ?)", "jack", "12345", "city");
            int c = 1 / 0;
            // 提交事务
            System.out.println("transaction commit...");
            platformTransactionManager.commit(transactionStatus);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            // 事务回滚
            System.out.println("transaction rollback..." + transactionStatus.isCompleted());
            platformTransactionManager.rollback(transactionStatus);
            return false;
        }
    }

事务代理实现和TransactionAspectSupport重要类

直接跟随上方异常栈去走debug代码

org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction中,创建一个事务

TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing进行了事务回滚
在这里插入图片描述

/**
 * Handle a throwable, completing the transaction.
 * We may commit or roll back, depending on the configuration.
 * @param txInfo information about the current transaction
 * @param ex throwable encountered
 */
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
	if (txInfo != null && txInfo.getTransactionStatus() != null) {
		if (logger.isTraceEnabled()) {
			logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
					"] after exception: " + ex);
		}
		if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
			try {
				txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
			}
			catch (TransactionSystemException ex2) {
				logger.error("Application exception overridden by rollback exception", ex);
				ex2.initApplicationException(ex);
				throw ex2;
			}
			catch (RuntimeException | Error ex2) {
				logger.error("Application exception overridden by rollback exception", ex);
				throw ex2;
			}
		}
		else {
			// We don't roll back on this exception.
			// Will still roll back if TransactionStatus.isRollbackOnly() is true.
			try {
				txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
			}
			catch (TransactionSystemException ex2) {
				logger.error("Application exception overridden by commit exception", ex);
				ex2.initApplicationException(ex);
				throw ex2;
			}
			catch (RuntimeException | Error ex2) {
				logger.error("Application exception overridden by commit exception", ex);
				throw ex2;
			}
		}
	}
}

在这里插入图片描述

debug到这里,然后Evaluate可以获取到两条记录
在这里插入图片描述

回滚完成后就只有一条记录:
在这里插入图片描述

另外可以看到事务的配置信息

  1. Spring事务传播方式是PROPAGATION_REQUIRED‌,即如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这也是最常见的选择。
  2. 隔离级别,使用数据库默认的(mysql默认隔离级别是REPEATABLE READ可重复读)
    在这里插入图片描述

回滚规则属性中也能看到设定的回滚规则:
在这里插入图片描述

复习Spring的事务传播机制有哪些

完全背不下来,直接理解记忆。

考虑如下代码的doLogic方法

class AService{

	@Autowired
	priavte BService bService;

	public void doLogic(){
		aaa();
		bService.bbb();
		ccc()
	}
}

可以看成如下,如果有事务,则是 有嵌套的,但是到底要不要,则可以自由决定

begin
	aaa()
    --------------
		begin
			bbb()
		commit();
    --------------
	ccc()
commit();

比如:bService里面可以

  1. 不要事务
  2. 要事务且用aService的事务(如果有)
  3. 要事务自己开启全新事务(这样里面就有三种不同的处理方式了)

对于aService:

  1. 本身没有事务
  2. 有事务, 如果有异常如何会滚:回滚自己的,还是把bService一起滚掉等等场景

这么一结合确实场景很多,Spring给出了如下的7种:
分别是:REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER和NESTED。

REQUIRED‌:如果当前存在事务,则加入该事务;如果不存在事务,则创建一个新的事务。这是Spring的默认传播机制,适用于大多数业务场景,确保多个事务操作在同一个事务中执行,以保持数据一致性‌

‌SUPPORTS‌:如果当前存在事务,则加入该事务;如果不存在事务,则以非事务方式执行。适用于那些不需要事务也能正确执行,但在事务环境下运行也不会造成任何问题的方法‌

‌MANDATORY‌:必须在一个已存在的事务中执行,如果当前没有事务则抛出异常。适用于那些必须在事务中执行的操作‌

‌REQUIRES_NEW‌:总是创建一个新的事务,如果当前存在事务,则将当前事务挂起,新的事务结束后,再恢复之前被挂起的事务。适用于那些需要在独立事务中执行的操作‌

‌NOT_SUPPORTED‌:不使用事务,如果当前存在事务,则将其挂起,直到该方法完成后再继续执行。适用于那些不需要事务的方法‌

‌NEVER‌:不允许在事务中执行,如果当前存在事务,则抛出异常。适用于那些必须在非事务环境中执行的操作‌


‌NESTED‌:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则新建一个事务。适用于需要嵌套事务的场景‌

实际工作中用到的事务处理

  1. dbOperate做了一系列数据库操作,必须再次之后进行callBack方法
method(){
	dbOpeate()
	TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization(){
 		@Override
        public void afterCompletion(int status) {
           callBack();
        }
    });
}
  1. 新事务处理完成后,再处理业务逻辑
@Transactional(rollbackFor = Exception.class)
void method(){
	try
		bService.getLock();
		cService.dbOperation();
	}finally{
		bService.releaseLock();
	}
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
void getLock(){

}

@Transactional(propagation = Propagation.REQUIRES_NEW)
void releaseLock(){

}

执行getLock和releaseLock是挂起method,自己开启新事务快速处理完成;因为数据库操作简单且快,不至于和后面的dbOperation产生模糊关系。

  1. 使用事务事件监听

@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)

一些列复杂操作,在事务前后有特定的操作,如统计、告知等

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2270528.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WebGL之Tree.js

tree基于WebGL的库绘制展示3D图形使用场景包括: 网页游&#xff1a;创建交互式的3D游戏&#xff0c;提供沉浸式的游戏体验。数据可视&#xff1a;将复杂的数据以3D形式展示&#xff0c;便于用户理解和分析。产品展&#xff1a;在电商网站上展示产品的3D模型&#xff0c;提供更…

图像识别-全连接层-卷积层-卷积层的计算-多输入通道场景-多输出通道场景-感受野-填充-VALID 与 SAME-stride-池化-CNN架构

文章目录 全连接层卷积神经网络的作用全连接层的问题场景图像处理和数据转换信息丢失的实例特征提取阶段分类阶段 卷积层卷积层的计算多输入通道场景多输出通道场景批量操作 感受野填充&#xff08;padding&#xff09;VALID 与 SAMEstride池化池化的作用 CNN架构 全连接层 卷…

MATLAB 车牌自动识别系统设计 SVM支持向量机方法 车牌识别

基于支持向量机&#xff08;SVM&#xff09;方法的车牌自动识别系统是一种利用SVM算法对车牌进行分类和识别的技术。该系统通过将车牌的图像处理和特征提取与SVM分类相结合&#xff0c;实现车牌的自动检测与识别。 1. 系统概述 车牌自动识别系统旨在从车辆图像中自动识别车牌…

《Vue3实战教程》39:Vue3无障碍访问

如果您有疑问&#xff0c;请观看视频教程《Vue3实战教程》 无障碍访问​ Web 无障碍访问 (也称为 a11y) 是指创建可供任何人使用的网站的做法——无论是身患某种障碍、通过慢速的网络连接访问、使用老旧或损坏的硬件&#xff0c;还是仅处于某种不方便的环境。例如&#xff0c;…

C++ 【回调函数】详解与代码解读

在现代软件开发中&#xff0c;回调函数是一个常用的工具&#xff0c;能够实现函数调用的延迟绑定&#xff0c;广泛应用于事件驱动、异步操作以及模块解耦等场景。本文将从基础概念、分类、实现方式到代码示例&#xff0c;全面讲解 C 回调函数的实现和应用。 什么是回调函数&…

No.1十六届蓝桥杯备战|第一个C++程序|cin和cout|命名空间

第一个C程序 基础程序 使用DevC5.4.0 写一个C程序 在屏幕上打印hello world #include <iostream> using namespace std;int main() {cout << "hello world" << endl;return 0; } 运行这个C程序 F9->编译 F10->运行 F11->编译运行 mai…

【Vim Masterclass 笔记05】第 4 章:Vim 的帮助系统与同步练习

文章目录 Section 4&#xff1a;The Vim Help System&#xff08;Vim 帮助系统&#xff09;S04L14 Getting Help1 打开帮助系统2 退出帮助系统3 查看具体命令的帮助文档4 查看帮助文档中的主题5 帮助文档间的上翻、下翻6 关于 linewise7 查看光标所在术语名词的帮助文档8 关于退…

印象笔记07——试一试PDF标注

印象笔记07——试一试PDF标注 [!CAUTION] 根据第六期&#xff0c;我再次查询了资料&#xff0c;印象笔记还是有一些可圈可点的功能的&#xff08;当然部分有平替&#xff09;&#xff0c;针对会员作用&#xff0c;开发使用场景虽然是逆向的&#xff0c;但我坚信这是一部分人的现…

JDK17源码分析Jdk动态代理底层原理

本文侧重分析JDK17中jdk动态代理的源码&#xff0c;若是想看JDK8源码分析可以看我的这一篇文章 JDK8源码分析Jdk动态代理底层原理-CSDN博客 两者之间有着略微的差别&#xff0c;JDK17在JDK8上改进了不少 目录 JDK 17的动态代理源码 核心入口方法 newProxyInstance 获取代理类…

【网络协议】开放式最短路径优先协议OSPF详解(一)

OSPF 是为取代 RIP 而开发的一种无类别的链路状态路由协议&#xff0c;它通过使用区域划分以实现更好的可扩展性。 文章目录 链路状态路由协议OSPF 的工作原理OSPF 数据包类型Dijkstra算法、管理距离与度量值OSPF的管理距离OSPF的度量值 链路状态路由协议的优势拓扑结构路由器O…

vim 的基础使用

目录 一&#xff1a;vim 介绍二&#xff1a;vim 特点三&#xff1a;vim 配置四&#xff1a;vim 使用1、vim 语法格式2、vim 普通模式&#xff08;1&#xff09;保存退出&#xff08;2&#xff09;光标跳转&#xff08;3&#xff09;文本删除&#xff08;4&#xff09;文本查找&…

为什么深度学习和神经网络要使用 GPU?

为什么深度学习和神经网络要使用 GPU&#xff1f; 本篇文章的目标是帮助初学者了解 CUDA 是什么&#xff0c;以及它如何与 PyTorch 配合使用&#xff0c;更重要的是&#xff0c;我们为何在神经网络编程中使用 GPU。 图形处理单元 (GPU) 要了解 CUDA&#xff0c;我们需要对图…

工厂模式与抽象工厂模式在Unity中的实际应用案例

一、实验目的 实践工厂模式和抽象工厂模式的实际应用。 创建一个小型的游戏场景&#xff0c;通过应用这些设计模式提升游戏的趣味性和可扩展性。 掌握在复杂场景中管理和使用不同类型的对象。 比较在实际游戏开发中不同设计模式的实际效果和应用场景。 学习如何进行简单的性…

jrc水体分类对水体二值掩码修正

使用deepwatermap生成的水体二值掩码中有部分区域由于被云挡住无法识别&#xff0c;造成水体不连续是使用jrc离线数据进行修正&#xff0c;jrc数据下载连接如下&#xff1a;https://global-surface-water.appspot.com/download 选择指定区域的数据集合下载如图&#xff1a; 使…

计算机网络 (20)高速以太网

一、发展背景 随着计算机技术和网络应用的不断发展&#xff0c;传统的以太网速率已逐渐无法满足日益增长的带宽需求。因此&#xff0c;高速以太网应运而生&#xff0c;它以提高数据传输速率为主要目标&#xff0c;不断推动着以太网技术的发展。 二、技术特点 高速传输&#xff…

基于SpringBoot的校园二手交易平台的设计与实现(源码+SQL+LW+部署讲解)

文章目录 摘 要1. 第1章 选题背景及研究意义1.1 选题背景1.2 研究意义1.3 论文结构安排 2. 第2章 相关开发技术2.1 前端技术2.2 后端技术2.3 数据库技术 3. 第3章 可行性及需求分析3.1 可行性分析3.2 系统需求分析 4. 第4章 系统概要设计4.1 系统功能模块设计4.2 数据库设计 5.…

2024年中国新能源汽车用车发展怎么样 PaperGPT(二)

用车趋势深入分析 接上文&#xff0c;2024年中国新能源汽车用车发展怎么样 PaperGPT&#xff08;一&#xff09;-CSDN博客本文将继续深入探讨新能源汽车的用车强度、充电行为以及充电设施的现状。 用车强度 月均行驶里程&#xff1a;2024年纯电车辆月均行驶超过1500公里&…

antd-vue - - - - - a-date-picker限制选择范围

antd-vue - - - - - a-date-picker限制选择范围 1. 效果展示2. 代码展示 1. 效果展示 如图&#xff1a;限制选择范围为 今年 & 去年 的 月份. 2. 代码展示 <template><a-date-picker:disabledDate"disabledDate"picker"month"/> &l…

滑动窗口、流量控制和拥塞控制

1. 确认应答机制 确认应答机制是计算机网络中&#xff0c;用于确保数据可靠传输的一种方法。 它通过发送 ACK 数据段来通知对方&#xff0c;每一个 ACK 数据段都有一个确认序号&#xff0c;表明&#xff1a; 确认序号之前的所有数据都已被接收&#xff0c;接下来从确认序号开…

TCP粘/拆包----自定义消息协议

今天是2024年12月31日&#xff0c;今年的最后一天&#xff0c;希望所有的努力在新的一年会有回报。❀ 无路可退&#xff0c;放弃很难&#xff0c;坚持很酷 TCP传输 是一种面向二进制的&#xff0c;流的传输。在传输过程中最大的问题是消息之间的边界不明确。而在服务端主要的…