当前位置: 首页 > article >正文

Spring Boot 中事务的用法详解

引言 

在 Spring Boot 中,事务管理是一个非常重要的功能,尤其是在涉及数据库操作的业务场景中。Spring 提供了强大的事务管理支持,能够帮助我们简化事务的管理和控制。本文将详细介绍 Spring Boot 中事务的用法,包括事务的基本概念、事务的配置、事务的传播行为、事务的隔离级别以及事务的回滚机制。

1. 事务的基本概念

事务(Transaction)是指一组数据库操作,这些操作要么全部成功,要么全部失败。事务的四大特性(ACID)包括:

  • 原子性(Atomicity):事务中的所有操作要么全部成功,要么全部失败。

  • 一致性(Consistency):事务执行前后,数据库的状态保持一致。

  • 隔离性(Isolation):多个事务并发执行时,彼此之间互不干扰。

  • 持久性(Durability):事务一旦提交,对数据库的修改是永久性的。

在 Spring Boot 中,事务管理是通过 @Transactional 注解来实现的。

2. Spring Boot 中事务的配置

2.1 启用事务管理

Spring Boot 默认已经集成了事务管理功能,只需要在配置类或启动类上添加 @EnableTransactionManagement 注解即可启用事务管理。

@SpringBootApplication
@EnableTransactionManagement // 启用事务管理
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}

2.2 配置数据源和事务管理器

Spring Boot 默认使用 DataSourceTransactionManager 作为事务管理器。如果你使用的是 Spring Data JPA,事务管理器会自动配置。

# application.yml
spring:datasource:url: jdbc:mysql://localhost:3306/mydbusername: rootpassword: rootdriver-class-name: com.mysql.cj.jdbc.Driver

3. 使用 @Transactional 注解

@Transactional 是 Spring 提供的事务管理注解,可以标注在类或方法上。标注在类上时,表示该类中的所有方法都启用事务管理;标注在方法上时,表示该方法启用事务管理。

@Service
public class UserService {@Autowiredprivate UserRepository userRepository;@Transactional // 开启事务  表示该方法开启了事务public void createUser(User user) {userRepository.save(user);}
}

3.2 事务的传播行为

事务的传播行为(Propagation)定义了事务方法之间的调用关系。Spring 提供了以下几种传播行为:

  • REQUIRED(默认):如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。(适用于大多数业务场景,尤其是需要保证多个操作在同一个事务中执行的场景。 例如,订单创建时需要同时更新订单表和库存表。)

  • REQUIRES_NEW:无论当前是否存在事务,都创建一个新的事务。(适用于需要独立事务的场景,尤其是日志记录、审计等操作。 例如,记录操作日志时,即使主事务失败,日志记录仍然需要成功。)

  • SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。(适用于不需要强制事务的场景,例如查询操作。 例如,查询用户信息时,如果调用方有事务,则加入事务;如果没有事务,则以非事务方式执行。)

  • NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则挂起该事务。(适用于不需要事务支持的场景,例如发送消息、调用外部接口等。 例如,发送短信通知时,不需要事务支持。)

  • MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(适用于强制要求调用方必须有事务的场景。 例如,某些核心业务逻辑必须在一个事务中执行。)

  • NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。(适用于强制要求调用方不能有事务的场景。 例如,某些只读操作或外部调用。)

  • NESTED:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则创建一个新的事务。(适用于需要部分回滚的场景。 例如,订单创建时需要更新多个表,如果某个表更新失败,只需要回滚该表的操作,而不影响其他表的操作。)

  • 示例:

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateUser(User user) {userRepository.save(user);
    }

    3.3 事务的隔离级别

    事务的隔离级别(Isolation)定义了事务之间的可见性。Spring 支持以下几种隔离级别:

  • DEFAULT:使用数据库的默认隔离级别。(适用于大多数通用场景,尤其是当你对数据库的默认行为没有特殊要求时。 如果你不确定应该选择哪种隔离级别,可以使用 DEFAULT,让数据库根据其默认行为处理事务。)

  • READ_UNCOMMITTED:允许读取未提交的数据变更,可能会导致脏读、幻读和不可重复读。(适用于对数据一致性要求不高的场景,例如统计数据的读取或日志记录。 不适用于涉及资金、订单等对数据一致性要求高的场景。)

  • READ_COMMITTED:只能读取已提交的数据,可以避免脏读,但可能会导致幻读和不可重复读。(适用于大多数业务场景,尤其是对数据一致性有一定要求但不需要严格隔离的场景。 例如,电商系统中的订单查询、用户信息查询等。)

  • REPEATABLE_READ:确保在同一事务中多次读取同一数据时结果一致,可以避免脏读和不可重复读,但可能会导致幻读。(适用于对数据一致性要求较高的场景,例如银行系统中的账户余额查询。 例如,在一个事务中多次读取同一账户的余额时,确保结果一致。)

  • SERIALIZABLE:最高隔离级别,确保事务串行执行,可以避免脏读、幻读和不可重复读(适用于对数据一致性要求极高的场景,例如金融系统中的资金清算、库存管理等。 由于性能开销较大,通常只在必要时使用。)

  • 示例:

    @Transactional(isolation = Isolation.READ_COMMITTED)
    public User getUserById(Long id) {return userRepository.findById(id).orElse(null);
    }

    3.4 事务的回滚机制

    默认情况下,Spring 会在方法抛出 RuntimeException 或 Error 时回滚事务。如果需要自定义回滚规则,可以通过 rollbackFor(哪些异常回滚) 和 noRollbackFor(哪些异常不会回滚) 属性来指定。

    示例:

    @Transactional(rollbackFor = Exception.class) // 所有异常都回滚
    public void updateUser(User user) throws Exception {userRepository.save(user);if (user.getName() == null) {throw new Exception("用户名不能为空"); // 抛出受检异常}
    }

    4. 事务的嵌套与传播行为

    在复杂的业务场景中,可能会存在事务方法调用事务方法的情况。此时,事务的传播行为决定了事务的嵌套方式。

  • 4.1 嵌套事务示例

    @Service
    public class OrderService {@Autowiredprivate UserService userService;@Transactional  //一级事务public void createOrder(Order order) {// 保存订单orderRepository.save(order);// 调用另一个事务方法userService.updateUser(order.getUser());}
    }@Service
    public class UserService {@Transactional(propagation = Propagation.REQUIRES_NEW) //二级事务public void updateUser(User user) {userRepository.save(user);}
    }

    在上面的示例中,createOrder 方法调用 updateUser 方法时,updateUser 方法会开启一个新的事务。

5. 事务的注意事项(事务不生效的几种情况)

  1. 事务方法的可见性

    • @Transactional 只能应用于 public 方法。如果应用于 private 或 protected 方法,事务将不会生效。Spring 的事务管理是基于代理模式实现的,代理对象只能拦截 public 方法。对于 private 或 protected 方法,Spring 无法生成代理,因此事务不会生效。

      @Service
      public class UserService {@Autowiredprivate UserRepository userRepository;// 正确:public 方法,事务生效@Transactionalpublic void createUser(User user) {userRepository.save(user);}// 错误:private 方法,事务不会生效@Transactionalprivate void updateUser(User user) {userRepository.save(user);}// 错误:protected 方法,事务不会生效@Transactionalprotected void deleteUser(Long userId) {userRepository.deleteById(userId);}
      }

  2. 事务的自我调用问题

    • 如果事务方法调用了同一个类中的另一个事务方法,事务的传播行为可能不会生效。这是因为Spring 的代理对象只能拦截从外部调用的方法。如果事务方法在同一个类中调用另一个事务方法,实际上是直接调用目标方法,而不是通过代理对象调用,因此事务的传播行为不会生效。

      @Service
      public class OrderService {@Autowiredprivate OrderRepository orderRepository;@Transactionalpublic void createOrder(Order order) {// 保存订单orderRepository.save(order);// 调用另一个事务方法(自我调用)updateInventory(order.getProductId(), order.getQuantity());}@Transactional(propagation = Propagation.REQUIRES_NEW)public void updateInventory(Long productId, int quantity) {// 更新库存逻辑}
      }

      在上面的示例中,createOrder 方法调用了 updateInventory 方法,但由于是自我调用,updateInventory 方法的事务传播行为(REQUIRES_NEW)不会生效。

    • 解决方法:

    • 将事务方法拆分到不同的类中
      将 updateInventory 方法移到另一个服务类中,通过依赖注入调用。

      @Service
      public class OrderService {@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate InventoryService inventoryService;@Transactionalpublic void createOrder(Order order) {// 保存订单orderRepository.save(order);// 调用另一个服务类的事务方法inventoryService.updateInventory(order.getProductId(), order.getQuantity());}
      }@Service
      public class InventoryService {@Transactional(propagation = Propagation.REQUIRES_NEW)public void updateInventory(Long productId, int quantity) {// 更新库存逻辑}
      }

  3. 事务的超时设置

    • 可以通过 @Transactional(timeout = 10) 设置事务的超时时间(单位为秒)。如果事务执行时间超过指定时间,事务将自动回滚。

      @Service
      public class ReportService {@Autowiredprivate ReportRepository reportRepository;@Transactional(timeout = 10) // 设置事务超时时间为 10 秒public void generateReport() {// 模拟耗时操作for (int i = 0; i < 1000000; i++) {reportRepository.save(new Report("Report " + i));}}
      }

      在上面的示例中,如果 generateReport 方法的执行时间超过 10 秒,事务将自动回滚。

 

6. 总结

Spring Boot 提供了强大的事务管理功能,通过 @Transactional 注解可以轻松实现事务的控制。在实际开发中,需要根据业务需求选择合适的传播行为和隔离级别,同时注意事务方法的可见性和自我调用问题。

通过本文的介绍,相信你已经掌握了 Spring Boot 中事务的基本用法。如果你有更多问题,欢迎在评论区留言讨论!

相关文章:

Spring Boot 中事务的用法详解

引言 在 Spring Boot 中&#xff0c;事务管理是一个非常重要的功能&#xff0c;尤其是在涉及数据库操作的业务场景中。Spring 提供了强大的事务管理支持&#xff0c;能够帮助我们简化事务的管理和控制。本文将详细介绍 Spring Boot 中事务的用法&#xff0c;包括事务的基本概…...

【react18】如何使用useReducer和useContext来实现一个todoList功能

重点知识点就是使用useReducer来攻坚小型的公共状态管理&#xff0c;useImmerReducer来实现数据的不可变 实现效果 实现代码 项目工程结构 App.js文件 import logo from "./logo.svg"; import "./App.css"; import TodoLists from "./comps/TodoLi…...

Android GreenDAO 适配 AGP 8.0+

在 Android 中使用 GreenDao&#xff0c;由于 GreenDao 现在不维护&#xff0c;所以更新到新版本的 Gradle 经常出问题&#xff0c;在这记录一些升级遇到的问题&#xff0c;并且记录解决方案。 博主博客 https://blog.uso6.comhttps://blog.csdn.net/dxk539687357 一、‘:app…...

一篇搞懂vue3中如何使用ref、reactive实现响应式数据

ref 可实现 基本类型、对象类型响应式数据 reactive&#xff1a;只能实现 对象类型响应式 ref实现 基本类型 数据响应式&#xff1a; <template><div class"person"><h2>姓名&#xff1a;{{ name }}</h2><h2>年龄&#xff1a;{{ ag…...

【HeadFirst系列之HeadFirst设计模式】第7天之命令模式:封装请求,轻松实现解耦!

命令模式&#xff1a;封装请求&#xff0c;轻松实现解耦&#xff01; 大家好&#xff01;今天我们来聊聊设计模式中的命令模式&#xff08;Command Pattern&#xff09;。如果你曾经需要将请求封装成对象&#xff0c;或者希望实现请求的撤销、重做等功能&#xff0c;那么命令模…...

简单封装一个websocket构造函数

问题描述 最近维护一个老项目&#xff0c;发现项目中有大量重复代码&#xff0c;特别是websocket的调用这一块&#xff0c;同样的代码复制了十几个页面&#xff0c;于是自己封装了一个websocket调用的构造函数。 export default class CreateWebSocket {constructor(url) {//…...

Linux-Ansible自动化运维

文章目录 自动化运维Ansible &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Linux专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2025年02月21日17点38分 自动化运维 自动化运维常用工具 Ansible 和 SaltStack 自动化运维优势&#xff1a; 服…...

uni-app(位置1)

文章目录 一、获取当前的地理位置、速度 uni.getLocation(OBJECT)二、打开地图选择位置 uni.chooseLocation(OBJECT)三、使用应用内置地图查看位置。uni.openLocation(OBJECT) 一、获取当前的地理位置、速度 uni.getLocation(OBJECT) App平台 manifest中配置好自己的地图厂商k…...

RabbitMQ服务异步通信

消息队列在使用过程中&#xff0c;面临着很多实际问题需要思考&#xff1a; 1. 消息可靠性 消息从发送&#xff0c;到消费者接收&#xff0c;会经理多个过程&#xff1a; 其中的每一步都可能导致消息丢失&#xff0c;常见的丢失原因包括&#xff1a; 发送时丢失&#xff1a; 生…...

CSS基础(浮动、相对定位、绝对定位、固定定位、粘性定位、版心、重置默认样式)

文章目录 1. 浮动&#xff08;float&#xff09;1.1 简介1.2 元素浮动后的特点1.3 脱离文档流示例图1.4 浮动产生的影响1.4.1 积极影响1.4.2 消极影响 1.5 解决浮动产生的影响1.5.1 清除浮动&#xff08;Clearfix&#xff09;1.5.2 创建新的块格式化上下文&#xff08;BFC&…...

Spring Cloud — Hystrix 服务隔离、请求缓存及合并

Hystrix 的核心是提供服务容错保护&#xff0c;防止任何单一依赖耗尽整个容器的全部用户线程。使用舱壁隔离模式&#xff0c;对资源或失败单元进行隔离&#xff0c;避免一个服务的失效导致整个系统垮掉&#xff08;雪崩效应&#xff09;。 1 Hystrix监控 Hystrix 提供了对服务…...

RagFlow+Ollama 构建RAG私有化知识库

RagFlowOllama 构建RAG私有化知识库 关于RAG一、什么是RAGFlow一、RAGFlow 安装配置测服已有服务&#xff1a; mysql、redis、elasticsearch 二、RAGFlow 配置 ollama&#xff1a;本地运行大型语言模型的工具软件。用户可以轻松下载、运行和管理各种开源 LLM。降低使用门槛&…...

【Linux】【网络】不同子网下的客户端和服务器通信

【Linux】【网络】不同子网下的客户端和服务器通信 前两天在进行socket()网络编程并进行测试时&#xff0c;发现在不同wifi下两个电脑无法进行连接&#xff0c;大概去查找了如何解决 看到可以使用 frp 这个快速反向代理实现。 frp 可让您将位于 NAT 或防火墙后面的本地服务器…...

SpringBoot教程(十四) SpringBoot之集成Redis

SpringBoot教程&#xff08;十四&#xff09; | SpringBoot之集成Redis 一、Redis集成简介二、集成步骤 2.1 添加依赖2.2 添加配置2.3 项目中使用之简单使用 &#xff08;举例讲解&#xff09;2.4 项目中使用之工具类封装 &#xff08;正式用这个&#xff09;2.5 序列化 &…...

DeepSeek掘金——VSCode 接入DeepSeek V3大模型,附使用说明

VSCode 接入DeepSeek V3大模型,附使用说明 由于近期 DeepSeek 使用人数激增,服务器压力较大,官网已 暂停充值入口 ,且接口响应也开始不稳定,建议使用第三方部署的 DeepSeek,如 硅基流动 或者使用其他模型/插件,如 豆包免费AI插件 MarsCode、阿里免费AI插件 TONGYI Lin…...

OpenHarmony分布式数据管理子系统

OpenHarmony分布式数据管理子系统 简介 目录 组件说明 分布式数据对象数据共享分布式数据服务Key-Value数据库首选项关系型数据库标准数据化通路 相关仓 简介 子系统介绍 分布式数据管理子系统支持单设备的各种结构化数据的持久化&#xff0c;以及跨设备之间数据的同步、…...

如何有效利用MYSQL的连接数

连接数配置2500~3000 依然发现连接不够用&#xff1f; -- 查看当前最大连接数 SHOW VARIABLES LIKE MAX_CONNECTIONS; -- 查看当前总链接数 SHOW STATUS LIKE Threads_connected; -- 查看当前进程明细 SHOW PROCESSLIST; 合理设置以下参数&#xff1a; 1. MySQL 的参数设置 …...

【Java学习】多态

面向对象系列三 一、方法相同 二、方法重写 1.概念 2.条件 三、向上转型 1.概念 2.方式 四、方法绑定 五、多态 一、方法相同 方法相同要求方法名相同、参数列表相同、返回值类型相同(与两方法修饰的访问限定符相不相同、静态非静态状态相不相同无关)&#xff0c;而且…...

单片机 Bootloade与二进制文件的生成

单片机的 Bootloader 是一种特殊的程序&#xff0c;负责在单片机上电后初始化硬件、更新用户应用程序&#xff08;固件&#xff09;&#xff0c;并将控制权移交给用户程序。以下是其运行机制和关键流程的详细说明&#xff1a; 1、单片机 Bootloader 的核心作用 固件更新&…...

MySQL数据库(3)—— 表操作

目录 一&#xff0c;创建表 1.1 创建表的SQL 1.2 演示 二&#xff0c;查看表 三&#xff0c;修改表 四&#xff0c;删除表 常用的表操作会涉及到两种SWL语句 DDL&#xff08;Data Definition Language&#xff09;数据定义语言&#xff1a;建表、改表、删表等&#xff0…...

Springboot + Ollama + IDEA + DeepSeek 搭建本地deepseek简单调用示例

1. 版本说明 springboot 版本 3.3.8 Java 版本 17 spring-ai 版本 1.0.0-M5 deepseek 模型 deepseek-r1:7b 需要注意一下Ollama的使用版本&#xff1a; 2. springboot项目搭建 可以集成在自己的项目里&#xff0c;也可以到 spring.io 生成一个项目 生成的话&#xff0c;如下…...

七星棋牌源码高阶技术指南:6端互通、200+子游戏玩法深度剖析与企业级搭建实战(完全开源)

在棋牌游戏行业高速发展的今天&#xff0c;如何构建一个具备高并发、强稳定性与多功能支持的棋牌游戏系统成为众多开发者和运营团队关注的焦点。七星棋牌全开源修复版源码 凭借其 六端互通、200子游戏玩法、多省区本地化支持&#xff0c;以及 乐豆系统、防沉迷、比赛场、AI智能…...

【深度学习在图像配准中的应用与挑战】

图像配准在深度学习中的解决方案越来越多&#xff0c;尤其是通过卷积神经网络&#xff08;CNN&#xff09;和生成对抗网络&#xff08;GAN&#xff09;等方法&#xff0c;可以显著提升图像配准的效果&#xff0c;尤其是在处理复杂的非刚性变换和大范围的图像差异时。 1. 基于深…...

HarmonyOS 开发套件 介绍 ——上篇

HarmonyOS 开发套件 介绍 ——上篇 在当今科技飞速发展的时代&#xff0c;操作系统作为智能设备的核心&#xff0c;其重要性不言而喻。而HarmonyOS&#xff0c;作为华为推出的全新操作系统&#xff0c;正以其独特的魅力和强大的功能&#xff0c;吸引着越来越多的开发者和用户的…...

跳跃游戏(力扣55)

题目问是否可以跳到数组最后一个下标&#xff0c;有的同学可能会思考如何模拟跳跃这个操作&#xff0c;但这是比较困难的&#xff0c;很容易把自己绕进去。可以换一种思路&#xff0c;我们不需要知道具体是如何跳到最后一个下标的&#xff0c;而是找到最大的跳跃范围。如果该跳…...

网络空间安全(1)web应用程序的发展历程

前言 Web应用程序的发展历程是一部技术创新与社会变革交织的长卷&#xff0c;从简单的文档共享系统到如今复杂、交互式、数据驱动的平台&#xff0c;经历了多个重要阶段。 一、起源与初期发展&#xff08;1989-1995年&#xff09; Web的诞生&#xff1a; 1989年&#xff0c;欧洲…...

机器学习 - 衡量模型的特性

最近我们陆续学习了机器学习的一些基础知识&#xff0c;本文来理解一下衡量机器学习模型的特性。了解机器学习模型的特性不仅有助于在理论上理解不同算法的工作原理&#xff0c;也能在实践中指导模型选择、参数调优、结果解释和系统部署&#xff0c;最终提高模型的实际应用效果…...

JUC并发—9.并发安全集合三

大纲 1.并发安全的数组列表CopyOnWriteArrayList 2.并发安全的链表队列ConcurrentLinkedQueue 3.并发编程中的阻塞队列概述 4.JUC的各种阻塞队列介绍 5.LinkedBlockingQueue的具体实现原理 6.基于两个队列实现的集群同步机制 1.并发安全的数组列表CopyOnWriteArrayList …...

Baklib云智协同:数字资产赋能企业效能跃升

内容概要 在数字化转型加速的背景下&#xff0c;Baklib通过构建智能化的知识中台架构&#xff0c;为企业打造了贯穿知识采集、整合、应用的全链路解决方案。该平台以动态知识图谱为核心技术底座&#xff0c;支持文档、音视频、代码等20余种格式的数字资产全生命周期管理&#…...

wordpress adrotate插件 文件上传漏洞

当你爆破进wordpress后台但权限不是管理员的时&#xff0c;如果你有adrotate插件操作权限可以用adrotate的文件上传功能get webshell 该漏洞需要AdRotate版本 < 5.13.3 第一步按顺序点击上传文件 在这里文件一定要压缩成zip格式&#xff0c;上传的时候也是上传这个zip 上…...