【Spring 篇】基于注解的Spring事务控制详解

在这里插入图片描述

嗨,亲爱的读者朋友们!欢迎来到这篇关于基于注解的Spring事务控制的博客。如果你曾为事务处理而头痛,那么这里将为你揭开事务的神秘面纱。我们将一步步深入探讨Spring事务的世界,用简单易懂的语言、充满情感色彩的文字,带你领略事务的奇妙之旅。

前言:什么是事务?

在我们踏入事务控制的舞台之前,让我们先来了解一下什么是事务。简而言之,事务是一系列操作,要么全部成功执行,要么全部失败回滚。这就好比你在玩电子游戏,要么通关,要么回到起点重新来过。在软件开发中,事务确保了数据的完整性和一致性,是我们保持代码健壮性的重要手段。

Spring事务管理初探

Spring框架为我们提供了一套强大而灵活的事务管理机制。而其中基于注解的事务控制,则是一种让我们事务处理变得轻松愉快的方式。不再需要繁琐的事务管理代码,一切都可以通过简单的注解来搞定。

让我们来看一个简单的例子,假设我们有一个银行服务类:

@Service
public class BankService {

    @Autowired
    private AccountRepository accountRepository;

    @Transactional
    public void transferMoney(String fromAccount, String toAccount, double amount) {
        // 从fromAccount扣除金额
        Account from = accountRepository.findByAccountNumber(fromAccount);
        from.setBalance(from.getBalance() - amount);
        accountRepository.save(from);

        // 向toAccount添加金额
        Account to = accountRepository.findByAccountNumber(toAccount);
        to.setBalance(to.getBalance() + amount);
        accountRepository.save(to);
    }
}

在这个例子中,通过在 transferMoney 方法上加上 @Transactional 注解,我们告诉Spring,这是一个事务性的方法。如果在方法执行期间发生异常,整个方法的操作将被回滚,保持数据的一致性。是不是感觉事务处理变得异常简单?

事务的传播行为:如何舞动事务的芭蕾

咱们来聊聊事务的传播行为。简而言之,传播行为定义了事务方法之间的关系。举个例子,假设我们有两个服务方法 A 和 B,A 调用了 B,那么事务传播行为就是规定了A和B之间的事务关系。

在Spring中,有几种常见的传播行为,比如 REQUIREDREQUIRES_NEWNESTED。让我们用一个小故事来解释这些概念。

小故事:Alice和Bob的银行冒险

有一天,Alice和Bob决定一同前往银行冒险。他们分别代表了两个服务方法 A 和 B,银行冒险就是一个大事务。让我们看看不同传播行为下的故事发展。

1. REQUIRED - 要共舞一场

Alice(方法A)和Bob(方法B)一起进入银行,决定共同完成这次冒险。如果Alice和Bob中任何一个遇到了困难(异常),整个冒险就失败,两人重新回到银行门口。这就是 REQUIRED 传播行为,他们共舞一场,遇到异常就一同失败。

@Transactional(propagation = Propagation.REQUIRED)
public void adventureWithBank() {
    aliceService.doSomething(); // Alice
    bobService.doSomethingElse(); // Bob
}
2. REQUIRES_NEW - 各自为政

Alice和Bob决定各自为政,独立进行银行冒险。无论其中一人失败,另一人都可以继续。这就是 REQUIRES_NEW 传播行为,各自为政,不受对方的事务影响。

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void aliceAdventures() {
    aliceService.doSomething(); // Alice
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void bobAdventures() {
    bobService.doSomethingElse(); // Bob
}
3. NESTED - 嵌套情感

Alice和Bob选择进行嵌套冒险,就像一个人在另一个人的故事里。如果Bob的冒险失败,他可以独立回到银行门口;但如果Alice的冒险失败,整个故事将重新开始。这就是 NESTED 传播行为,嵌套在对方的事务中。

@Transactional(propagation = Propagation.NESTED)
public void aliceAdventures() {
    aliceService.doSomething(); // Alice
}

@Transactional(propagation = Propagation.NESTED)
public void bobAdventures() {
    bobService.doSomethingElse(); // Bob
}

这些故事或许显得幼稚,但通过这种方式,你可以轻松理解不同传播行为的含义。

隔离级别:在不同舞台上的表演

事务的隔离级别是事务管理中另一个关键概念。隔离级别定义了多个事务之间的可见性和影响关系。Spring支持的隔离级别有 DEFAULTREAD_UNCOMMITTEDREAD_COMMITTEDREPEATABLE_READSERIALIZABLE

我们来看一个简单的例子,通过不同的隔离级别来理解事务的表演。

小故事:隔离级别的舞台

在这个故事中,我们有两位演员,Alice和Bob,代表两个事务。银行就是事务的舞台,而不同的隔离级别就是这场表演的不同舞台设置。

1. READ_UNCOMMITTED - 公开彩排

Alice和Bob在银行里进行公开彩排,他们可以随意看到对方的动作,即使对方的动作还没有提交。这就是 READ_UNCOMMITTED 隔离级别,即一个事务可以看到另一个事务未提交的数据。

@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void alicePerformance() {
    aliceService.doSomething(); // Alice
}

@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void bobPerformance() {
    bobService.doSomethingElse(); // Bob
}
2. READ_COMMITTED - 隐蔽彩排

Alice和Bob进行了隐蔽的彩排,只有当对方的动作被提交后,才能看到。这就是 READ_COMMITTED 隔离级别,即一个事务只能看到另一个事务已经提交的数据。

@Transactional(isolation = Isolation.READ_COMMITTED)
public void alicePerformance() {
    aliceService.doSomething(); // Alice
}

@Transactional(isolation = Isolation.READ_COMMITTED)
public void bobPerformance() {
    bobService.doSomethingElse(); // Bob
}
3. SERIALIZABLE - 隔离彩排

Alice和Bob决定进行严格的隔离彩排,即一个事务完全看不到另一个事务的表演。这就是 SERIALIZABLE 隔离级别,即一个事务执行时,其他事务无法对相同的数据进行更新。

@Transactional(isolation = Isolation.SERIALIZABLE)
public void alicePerformance() {
    aliceService.doSomething(); // Alice
}

@Transactional(isolation = Isolation.SERIALIZABLE)
public void bobPerformance() {
    bobService.doSomethingElse(); // Bob
}

通过这个小故事,相信你对隔离级别有了更加生动的理解。

超时设置:等待表演的结束

有时候,我们可能希望限制事务的执行时间,以防止某个事务长时间占用资源。@Transactional 注解允许我们设置事务的超时时间,单位是秒。这就像是告诉演员们,你们的表演时间有限,不能一直霸占舞台。

@Transactional(timeout = 60)
public void alicePerformance() {
    aliceService.doSomething(); // Alice
}

在这个例子中,我们将 timeout 设置为60秒,表示这个事务的表演时间不得超过60秒。如果时间到了,不管表演是否结束,都要结束这场表演。

回滚控制:遇到意外,退场重演

在事务处理中,异常是一个无法避免的问题。Spring框架提供了 @Rollback 注解,用于控制事务是否回滚。默认情况下,Spring事务将在遇到运行时异常时回滚,但我们也可以通过 @Rollback 注解来手动控制回滚。

@Transactional
@Rollback(false)
public void alicePerformance() {
    aliceService.doSomething(); // Alice
}

在这个例子中,通过 @Rollback(false) 明确告诉Spring,即使在方法中抛出异常,也不要回滚事务。这种情况可能在我们需要记录异常情况但仍然希望保留部分已执行操作时有用。

读写操作的组合:舞台上的交响乐

在数据库事务中,读写操作的组合也是需要考虑的因素。Spring提供了 @Transactional 注解的 readOnly 属性,用于指定事务是否只读。

@Transactional(readOnly = true)
public List<Account> getAllAccounts() {
    return accountRepository.findAll();
}

在上述例子中,我们标注了 @Transactional(readOnly = true),表示这个事务只包含读操作,不包含写操作。这有助于提高数据库的性能,因为只读事务通常可以避免获得数据库写锁。

结语:跟着音乐的节奏,轻松驾驭事务的舞台

通过这篇博客,我们深入浅出地探讨了基于注解的Spring事务控制。从事务的概念开始,逐步介绍了 @Transactional 注解、事务的传播行为、隔离级别、超时设置、回滚控制、以及一些常见的使用场景。通过生动的小故事和实际的代码示例,相信你对Spring事务管理有了更加深刻的理解。

在这个舞台上,你不再是被事务搞得头痛的观众,而是优雅地跟着音乐的节奏,轻松驾驭着事务的舞台。希望这篇博客对于初学者来说是一次愉快的学习之旅,让你能够在事务的世界里游刃有余。如果你有任何疑问或者想要分享自己的经验,不妨在评论区留下你的足迹。让我们一起共同探索事务控制的奥秘,愉快地编写出高质量的、可靠的代码。感谢你的阅读,希望你在事务的舞台上能够畅快淋漓地表演!🎭💃

作者信息

作者 : 繁依Fanyi
CSDN: https://techfanyi.blog.csdn.net
掘金:https://juejin.cn/user/4154386571867191

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv5改进系列(25)——添加LSKNet注意力机制(大选择性卷积核的领域首次探索)

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制 YOLOv5改进系

探索SQL性能优化之道:实用技巧与最佳实践

SQL性能优化可能是每个数据库管理员和开发者在日常工作中必不可少的一个环节。在大数据时代&#xff0c;为确保数据库系统的响应速度和稳定性&#xff0c;掌握一些实用的SQL优化技巧至关重要。 本文将带着开发人员走进SQL性能优化的世界&#xff0c;深入剖析实用技巧和最佳实践…

ssm基于Java的超市管理系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本超市管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息&am…

关于Python里xlwings库对Excel表格的操作(三十二)

这篇小笔记主要记录如何【如何使用“Chart类”、“Api类"和“Axes函数”设置坐标轴标题文本内容】。 前面的小笔记已整理成目录&#xff0c;可点链接去目录寻找所需更方便。 【目录部分内容如下】【点击此处可进入目录】 &#xff08;1&#xff09;如何安装导入xlwings库…

如何解决NAND系统性能问题?--NAND分类

一、故事引言 想象一下&#xff0c;你正在管理一座神奇的数据仓库&#xff0c;这个仓库没有沉重的门、旋转的磁盘和机械手臂&#xff0c;而是由一群训练有素的“数据小飞侠”组成。这些小飞侠们居住在一个叫做闪存芯片&#xff08;NAND Flash&#xff0c;本文主人公&#xff0…

Java版企业电子招投标系统源代码,支持二次开发,采用Spring cloud技术

在数字化时代&#xff0c;采购管理也正经历着前所未有的变革。全过程数字化采购管理成为了企业追求高效、透明和规范的关键。该系统通过Spring Cloud、Spring Boot2、Mybatis等先进技术&#xff0c;打造了从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通过…

LeetCode刷题:141. 环形链表

题目&#xff1a; 是否独立解答出&#xff1a;否&#xff0c;有思路&#xff0c;但是代码报错&#xff0c;参考解题代码后&#xff0c;修改通过 解题思路&#xff1a;利用循环与哈希表存储每一个节点&#xff0c;如果发现添加不进去说明&#xff0c;存在环&#xff0c;正常来说…

Flutter之配置环境创建第一个项目

随着时代发展&#xff0c;使用Flutter开发的项目越来越多&#xff0c;于是踏上了Flutter开发之路。 作为一个Android开发人员&#xff0c;也只能被卷到与时俱进&#xff0c;下面一起创建一个Flutter项目吧。 一、Android开发&#xff0c;电脑上已经具备了的条件&#xff1a; …

基于springboot+vue药店管理系统

摘要 药店管理系统的设计和应用在当前社会背景下具有巨大的实际意义和社会价值。随着医药行业的不断发展和社会健康水平的提高&#xff0c;药店作为医疗服务的一部分&#xff0c;其管理方式也需要不断创新与优化。该系统的研究不仅关系到单一药店的运营效率&#xff0c;更涉及到…

软件包安装

1.软件包分类 1.1软件包的分类 源码包二进制包脚本安装包 1.2源码包 1.2.1源码包的样子 源码包可以认为是利用不同的计算机语言而写的包, 我们打开相应的文件也能看到相应的源码 1.2.2源码包的特点 源码包的优点: 开源, 如果有足够的能力, 可以修改源代码可以自由选择…

如何在Linux部署OpenGauss数据管理系统并实现固定公网地址访问

文章目录 前言1. Linux 安装 openGauss2. Linux 安装cpolar3. 创建openGauss主节点端口号公网地址4. 远程连接openGauss5. 固定连接TCP公网地址6. 固定地址连接测试 前言 openGauss是一款开源关系型数据库管理系统&#xff0c;采用木兰宽松许可证v2发行。openGauss内核深度融合…

fastadmin 框架如何移除图片上传后预览中的删除按钮

在FastAdmin中&#xff0c;当我们启用了图片上传预览时&#xff0c;在预览区域会自动生成预览图和删除按钮&#xff0c;如下图&#xff1a; 如果我们想上移除掉这里的删除按钮&#xff0c;则需要启用自定义预览模板的功能。 首先我们找到视图中我们的预览容器&#xff0c;比如…

Postman进行Soap webservice接口测试

许多人认为Postman是高级REST客户端&#xff0c;Postman是处理通过HTTP发送的请求的工具。其实Postman也可以测试与协议无关的SOAP webservice api接口。 要使用Postman发出SOAP请求&#xff0c;请执行以下操作&#xff1a; 1、提供SOAP端点作为URL&#xff0c;可以使用SOAP的W…

Vue入门六(前端路由的概念与原理|Vue-router简单使用|登录跳转案例|scoped样式)

文章目录 前要&#xff1a;前端路由的概念与原理1&#xff09;什么是路由2&#xff09;SPA与前端路由3&#xff09;什么是前端路由4&#xff09;前端路由的工作方式 一、Vue-router简单使用1&#xff09;什么是vue-router2) vue-router 安装和配置的步骤① 安装 vue-router 包②…

第11章 GUI Page495~496 步骤三十一:另存为别的文件,为TrySaveFile()入参设置一些位操作

工程二 头文件中为TrySaveFile()入参设置一些位操作&#xff0c;修改一下TrySaveFile()的入参类型 修改TrySaveFile()的实现&#xff1a; 修改“保存”菜单项挂接事件响应函数: 修改“另存为”菜单项挂接事件响应函数

kylin集群反向代理(健康检查)

前面一篇文章提到了使用nginx来对kylin集群进行反向代理&#xff0c; kylin集群使用nginx反向代理-CSDN博客文章浏览阅读349次&#xff0c;点赞8次&#xff0c;收藏9次。由于是同一个集群的&#xff0c;元数据没有变化&#xff0c;所以&#xff0c;直接将原本的kylin使用scp的…

大模型学习与实践笔记(四)

一、大模型开发范式 RAG&#xff08;Retrieval Augmented Generation&#xff09;检索增强生成&#xff0c;即大模型LLM在回答问题或生成文本时&#xff0c;会先从大量的文档中检索出相关信息&#xff0c;然后基于这些检索出的信息进行回答或生成文本&#xff0c;从而可以提高回…

使用组合框QComboBox模拟购物车

1.组合框: QComboBox 组合框&#xff1a;QComboBox 用于存放一些列表项 实例化 //实例化QComboBox* comboBox new QComboBox(this);1.1 代码实现 1.1.1 组合框的基本函数 QComboBox dialog.cpp #include "dialog.h" #include "ui_dialog.h"Dialog::Dialog…

大数据实时抓取软件:Maxwell学习网站的高效框架!

介绍&#xff1a;Maxwell是由美国Zendesk开源的&#xff0c;使用Java编写的MySQL实时抓取软件。它能够实时读取MySQL的二进制日志&#xff08;Binlog&#xff09;&#xff0c;并将这些信息生成为JSON格式的消息。进一步地&#xff0c;Maxwell将这些消息作为生产者发送给Kafka、…

【Android+物联网】Android封装MQTT连接阿里云物联网平台

前言&#xff1a; 亲测可行&#xff0c;本文实现Android封装MQTT连接阿里云物联网平台。将MQTT协议和连接阿里云平台的操作通过Android studio写入APP中&#xff0c;并简单设计UI。实现手机APP远程控制单片机LED灯亮灭的功能。 关于《Android软件开发》&#xff0c;见如下专栏…