springboot-@Transactional

news/2025/10/28 8:28:29/文章来源:https://www.cnblogs.com/hanease/p/19170681
springboot @Transactional
 
在 Spring Boot 中,@Transactional是声明式事务管理的核心注解,用于简化事务控制逻辑。它基于 AOP(面向切面编程)实现,通过注解声明方法或类需要在事务中运行,从而保证数据操作的原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)(即 ACID 特性)。

一、基本作用

@Transactional的核心作用是:自动为标注的方法或类添加事务管理逻辑(如事务开启、提交、回滚等),无需手动编写try-catchTransactionStatus相关代码。

二、使用位置

  • 方法上:仅对当前方法生效。
  • 类上:对类中所有public 方法生效(方法上的注解会覆盖类上的配置)。

三、核心属性

@Transactional提供了多个属性用于定制事务行为,常用属性如下:
属性名作用可选值(常用)
propagation 事务传播行为(定义方法间事务的嵌套规则) REQUIRED(默认)、REQUIRES_NEWSUPPORTSMANDATORYNEVER
isolation 事务隔离级别(解决并发问题:脏读、不可重复读、幻读) DEFAULT(默认,使用数据库隔离级别)、READ_COMMITTEDREPEATABLE_READ
readOnly 是否为只读事务(查询操作建议设为true,优化性能) true/false(默认false
rollbackFor 指定哪些异常触发事务回滚(默认仅对RuntimeExceptionError回滚) 异常类数组(如{Exception.class}
noRollbackFor 指定哪些异常不触发事务回滚 异常类数组(如{BusinessException.class}
timeout 事务超时时间(超过时间未完成则回滚,单位:秒) 整数(默认-1,表示不超时)

1. 事务传播行为(propagation)

定义多个事务方法嵌套调用时,事务的创建 / 关联规则(最常用的两个):
  • REQUIRED(默认):如果当前存在事务,则加入该事务;如果没有,则新建一个事务。
     
    例:ServiceA.methodA(带事务)调用 ServiceB.methodB(REQUIRED),methodB 会加入 methodA 的事务,若 methodB 失败,整个事务回滚。
  • REQUIRES_NEW:无论当前是否有事务,都新建一个事务;原事务会被挂起,直到新事务完成。
     
    例:methodA(事务)调用 methodB(REQUIRES_NEW),methodB 的事务独立,即使 methodB 失败,仅回滚自身,不影响 methodA 的事务。

2. 事务隔离级别(isolation)

解决并发场景下的事务冲突问题(依赖数据库支持):
  • DEFAULT:使用数据库默认隔离级别(MySQL 默认REPEATABLE_READ,Oracle 默认READ_COMMITTED)。
  • READ_COMMITTED:只能读取已提交的数据,避免脏读(读取未提交的数据)。
  • REPEATABLE_READ:保证多次读取同一数据结果一致,避免不可重复读(两次读取数据不一致)。
  • SERIALIZABLE:最高隔离级别,完全串行化执行,避免幻读(读取到新增的数据),但性能最差。

四、使用示例

java
 
运行
 
 
 
 
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;// 声明事务:传播行为REQUIRED,对所有Exception回滚,超时30秒@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, timeout = 30)public void transferMoney(Long fromId, Long toId, BigDecimal amount) throws Exception {// 扣钱userMapper.decreaseBalance(fromId, amount);// 模拟异常(如网络波动)if (amount.compareTo(new BigDecimal("10000")) > 0) {throw new Exception("转账金额过大"); // 触发回滚}// 加钱userMapper.increaseBalance(toId, amount);}
}
 

五、注意事项(避坑点)

  1. 仅对 public 方法生效:Spring AOP 默认只代理public方法,非public方法(如privateprotected)的@Transactional会失效。
  2. 自调用事务失效:同一类中,无事务的方法 A 调用有事务的方法 B 时,B 的事务会失效(因未经过 Spring 代理对象)。解决:注入自身代理对象(@Autowired private UserService self;),通过self.methodB()调用。
  3. 异常被捕获会导致回滚失效:若方法内部捕获异常且未重新抛出(如try-catch后不throw),Spring 无法感知异常,事务不会回滚。解决:捕获后需重新抛出异常(如throw new RuntimeException(e))。
  4. 数据库引擎支持:事务依赖数据库支持,例如 MySQL 的MyISAM引擎不支持事务,需使用InnoDB
  5. rollbackFor 默认行为:默认仅对RuntimeException(非检查异常)和Error回滚,对Exception(检查异常,如IOException)不回滚。若需对检查异常回滚,需显式指定rollbackFor = Exception.class

总结

@Transactional是 Spring Boot 中简化事务管理的核心工具,通过合理配置传播行为、隔离级别等属性,并规避使用中的常见问题,可有效保证数据操作的一致性。
 
@Transactional 事务注入案例
 
下面通过一个订单创建与库存扣减的业务场景,展示@Transactional事务注入(即事务在多个组件 / 方法间的传播与协同)的具体案例。该案例将包含 Service 间调用、事务传播行为的实际效果,以及常见问题的对比。

场景说明

业务流程:用户创建订单时,需要完成两个核心操作 ——创建订单记录和扣减商品库存。这两个操作必须在同一个事务中:要么都成功,要么都失败(例如库存不足时,订单需回滚)。额外需求:无论订单创建成功与否,都需要记录操作日志(日志记录需独立事务,不受主事务影响)。

技术依赖

  • Spring Boot 2.7.x
  • MyBatis(数据访问,也可替换为 JPA)
  • MySQL(InnoDB 引擎,支持事务)

代码实现

1. 实体类

java
 
运行
 
 
 
 
// 订单实体
@Data
public class Order {private Long id;private Long userId;private Long productId;private Integer quantity; // 购买数量private LocalDateTime createTime;
}// 商品实体(库存)
@Data
public class Product {private Long id;private String name;private Integer stock; // 库存数量
}// 操作日志实体
@Data
public class OperateLog {private Long id;private String content; // 日志内容private LocalDateTime createTime;
}
 

2. 数据访问层(Mapper)

java
 
运行
 
 
 
 
// 订单Mapper
@Mapper
public interface OrderMapper {// 插入订单@Insert("INSERT INTO `order`(user_id, product_id, quantity, create_time) " +"VALUES(#{userId}, #{productId}, #{quantity}, #{createTime})")void insert(Order order);
}// 商品Mapper
@Mapper
public interface ProductMapper {// 扣减库存(where条件确保库存充足时才扣减)@Update("UPDATE product SET stock = stock - #{quantity} " +"WHERE id = #{productId} AND stock >= #{quantity}")int decreaseStock(@Param("productId") Long productId, @Param("quantity") Integer quantity);// 查询商品@Select("SELECT * FROM product WHERE id = #{id}")Product selectById(Long id);
}// 日志Mapper
@Mapper
public interface OperateLogMapper {@Insert("INSERT INTO operate_log(content, create_time) VALUES(#{content}, #{createTime})")void insert(OperateLog log);
}
 

3. Service 层(核心事务逻辑)

3.1 库存服务(ProductService)
负责扣减库存,声明事务(默认传播行为REQUIRED,加入调用者的事务)。
java
 
运行
 
 
 
 
@Service
public class ProductService {@Autowiredprivate ProductMapper productMapper;/*** 扣减库存(事务传播行为:REQUIRED,默认)* 若库存不足,抛出异常触发回滚*/@Transactionalpublic void decreaseStock(Long productId, Integer quantity) {// 扣减库存(返回影响行数,0表示库存不足)int rows = productMapper.decreaseStock(productId, quantity);if (rows == 0) {// 库存不足,抛出异常(会被上层事务捕获并触发回滚)throw new RuntimeException("商品库存不足");}}
}
 
3.2 日志服务(LogService)
负责记录日志,使用REQUIRES_NEW传播行为,确保日志事务独立(不受主事务影响)。
java
 
运行
 
 
 
 
@Service
public class LogService {@Autowiredprivate OperateLogMapper logMapper;/*** 记录日志(事务传播行为:REQUIRES_NEW,独立事务)*/@Transactional(propagation = Propagation.REQUIRES_NEW)public void recordLog(String content) {OperateLog log = new OperateLog();log.setContent(content);log.setCreateTime(LocalDateTime.now());logMapper.insert(log);}
}
 
3.3 订单服务(OrderService)
核心业务逻辑:创建订单 + 调用库存服务扣减库存 + 调用日志服务记录日志。声明事务(REQUIRED),确保订单创建和库存扣减在同一事务中。
java
 
运行
 
 
 
 
@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate ProductService productService; // 注入库存服务(事务协同)@Autowiredprivate LogService logService; // 注入日志服务(独立事务)/*** 创建订单(主事务:REQUIRED)* 流程:扣减库存 -> 创建订单 -> 记录日志(成功/失败)*/@Transactional(rollbackFor = Exception.class) // 对所有异常回滚public void createOrder(Long userId, Long productId, Integer quantity) {String logContent;try {// 1. 扣减库存(调用ProductService,加入当前事务)productService.decreaseStock(productId, quantity);// 2. 创建订单(与扣减库存同事务)Order order = new Order();order.setUserId(userId);order.setProductId(productId);order.setQuantity(quantity);order.setCreateTime(LocalDateTime.now());orderMapper.insert(order);logContent = "订单创建成功:用户" + userId + "购买商品" + productId + ",数量" + quantity;} catch (Exception e) {// 3. 若异常(如库存不足),记录失败日志logContent = "订单创建失败:" + e.getMessage();throw e; // 关键:必须重新抛出异常,否则主事务不会回滚!} finally {// 4. 记录日志(调用LogService,独立事务,无论成败都会执行)logService.recordLog(logContent);}}
}
 

4. Controller 层(接口调用)

java
 
运行
 
 
 
 
@RestController
@RequestMapping("/orders")
public class OrderController {@Autowiredprivate OrderService orderService;@PostMappingpublic String createOrder(@RequestParam Long userId,@RequestParam Long productId,@RequestParam Integer quantity) {try {orderService.createOrder(userId, productId, quantity);return "订单创建成功";} catch (Exception e) {return "订单创建失败:" + e.getMessage();}}
}
 

事务注入效果测试

测试 1:正常流程(库存充足)

  • 操作:调用接口,购买库存充足的商品(如商品 A 库存 100,购买 10)。
  • 结果:
    • 库存扣减成功(100→90)。
    • 订单表新增一条记录。
    • 日志表新增一条 “成功” 日志。
    • 所有操作在事务中完成,数据一致。

测试 2:异常流程(库存不足)

  • 操作:调用接口,购买库存不足的商品(如商品 A 库存 5,购买 10)。
  • 结果:
    • ProductService.decreaseStock扣减库存失败,抛出RuntimeException
    • OrderService.createOrder捕获异常后重新抛出,触发主事务回滚:订单记录不会插入数据库。
    • LogService.recordLogREQUIRES_NEW,独立事务提交:日志表新增一条 “失败” 日志。
    • 最终状态:库存不变,无订单,有失败日志(符合业务预期)。

测试 3:验证事务传播行为

  • LogService.recordLog使用默认REQUIRED传播行为:
     
    当主事务回滚时,日志的插入也会被回滚(不符合 “必须记录日志” 的需求)。
     
    这就是REQUIRES_NEW的作用 —— 强制新建事务,确保日志独立。

关键注意点

  1. 事务注入的核心是传播行为:多个 Service 方法调用时,propagation属性决定事务是否共享、新建或挂起(如案例中REQUIREDREQUIRES_NEW的区别)。
  2. 异常必须抛出:OrderServicecatch异常后必须throw e,否则 Spring 无法感知异常,主事务不会回滚(这是最常见的坑)。
  3. 避免自调用失效:若OrderService中一个无事务的方法 A 调用自身有事务的方法 B,B 的事务会失效(需通过@Autowired注入自身代理对象调用)。
  4. 数据库支持:确保使用 InnoDB 引擎(MyISAM 不支持事务)。
通过这个案例可以清晰看到:@Transactional通过 “注入”(即不同 Service 间的调用)实现了事务的协同管理,既保证了核心业务的原子性,又通过传播行为满足了特殊场景(如独立日志)的需求。

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

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

相关文章

2025年耐用的不锈钢防火阀厂家最新推荐权威榜

2025年耐用的不锈钢防火阀厂家最新推荐权威榜 在建筑消防系统中,不锈钢防火阀是保障消防安全的关键设备之一。其耐高温、耐腐蚀的特性使其在商业建筑、工业设施、医院、地铁等场所广泛应用。随着2025年消防设备标准的…

HTTP协议中三次握手 四次挥手是什么

在HTTP协议中,“三次握手”和“四次挥手”本质是 TCP协议的连接与断开机制(HTTP基于TCP传输层协议实现可靠通信,自身不涉及握手/挥手),核心是确保通信双方“能发、能收”,避免数据丢失或连接混乱。 一、三次握手…

四次挥手

第一次是客服端发给服务器的,表示用户无数据请求,却还可以接收到服务器的数据。 第二次是服务器发给客户端的,服务器收到请求,处于半关闭的状态。 第三次是服务器发给客户端的,服务器发送完请求后,发起关闭请求,…

2025年10月重庆保洁公司推荐榜:五强对比评测

如果您正在重庆寻找一家“能把活干细、把风险控住、把预算卡准”的保洁公司,大概率会陷入三重焦虑:一是网上信息雷同,分不清谁家真自营;二是报价跨度大,同一项目从几千到几万都有,怕踩“低价陷阱”;三是高空、开…

2025年优质的高低压配电柜厂家实力及用户口碑排行榜

2025年优质的高低压配电柜厂家实力及用户口碑排行榜在电力设备行业中,高低压配电柜作为电力系统的核心组成部分,其质量与性能直接关系到整个电力系统的安全稳定运行。随着我国电力基础设施建设的不断推进和新能源产业…

《程序员修炼之道:从小工到专家》感悟

初为“小工”,沉迷于用代码实现功能,视“跑通”为终点,却常因逻辑漏洞、冗余代码陷入返工。后来才懂,编程不止是“写”,更是“思”。 专家的核心是建立系统思维:先拆解需求本质,再设计可扩展架构,如同先画蓝图…

2025年有实力的薄膜电动搬运车厂家推荐及选择指南

2025年有实力的薄膜电动搬运车厂家推荐及选择指南 随着物流行业的快速发展,薄膜电动搬运车在仓储、制造业、食品加工等领域的需求日益增长。选择一家实力雄厚、技术先进、服务完善的搬运车厂家至关重要。本文将推荐2…

【GitHub每日速递 251028】Open Notebook:隐私至上,16+AI 模型解锁科研笔记新玩法!

原文:https://mp.weixin.qq.com/s/1AGCABJHMGzXZ3tYFl4vqg Open Notebook:隐私至上,16+AI 模型解锁科研笔记新玩法! 项目地址:https://github.com/lfnovo/open-notebook 主要语言:TypeScript stars: 7.4k项目简介…

2025年可靠的厚壁不锈钢管行业内知名厂家排行榜

2025年可靠的厚壁不锈钢管行业内知名厂家排行榜行业概述厚壁不锈钢管作为工业制造和建筑装饰领域的重要材料,凭借其优异的耐腐蚀性、高强度和使用寿命长等特点,在石油化工、食品加工、医疗器械、建筑装饰等行业中占据…

2025年知名的pfa管厂家最新推荐权威榜

2025年知名的PFA管厂家最新推荐权威榜 行业背景与PFA管的重要性 PFA管(全氟烷氧基烷烃管)因其优异的耐化学腐蚀性、高纯度、耐高温(-200C至260C)和低渗透性,成为半导体、化工、医药、新能源等高端制造领域的核心…

2025年知名的净化材料净化板最新TOP品牌厂家排行

2025年知名的净化材料净化板最新TOP品牌厂家排行 在建筑、医疗、电子、食品等行业中,净化材料的需求日益增长,尤其是净化板作为核心材料,其质量直接影响净化工程的稳定性和安全性。2025年,随着技术的进步和市场的…

2025年耐用的管式换热器厂家最新权威实力榜

2025年耐用的管式换热器厂家最新权威实力榜在工业制造、化工生产、能源利用等领域,管式换热器作为关键的热交换设备,其性能和质量直接影响生产效率和能源消耗。随着环保要求的提高和节能减排政策的推行,高效、耐用的…

2025年质量好的高强度钢丝绳索具厂家选购指南与推荐

2025年质量好的高强度钢丝绳索具厂家选购指南与推荐在工业制造、建筑、航运和采矿等领域,高强度钢丝绳索具是不可或缺的关键部件。随着2025年工业4.0的深入推进,市场对钢丝绳索具的质量、安全性和耐用性要求越来越高…

2025年口碑好的清洗机用户好评厂家排行

2025年口碑好的清洗机用户好评厂家排行 在工业制造领域,清洗设备是保障生产效率和产品质量的重要环节。随着技术的不断进步,清洗机的智能化、高效化和环保性能成为用户选择的关键因素。2025年,市场上涌现出一批口碑…

[转]Spring 之MultipartFile转换File 并鉴别File Mine Type 类型

原文地址:Spring 之MultipartFile转换File 并鉴别File Mine Type 类型_spring mimetype-CSDN博客 常见 MIME 类型列表扩展名 文档类型 MIME 类型.aac AAC audio audio/aac.abw AbiWord document application/x-abiword…

2025年热门的双锥干燥机厂家推荐及选购指南

2025年热门的双锥干燥机厂家推荐及选购指南 引言 双锥干燥机是一种广泛应用于医药、化工、食品等行业的高效干燥设备,其独特的双锥结构设计可实现均匀加热、高效干燥,并适用于真空条件下的物料处理。随着行业需求的…

Win11右键菜单修改为传统Win10右键风格

修改为 win10 风格 reg.exe add "HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32" /f /ve恢复为 win11 风格 reg.exe delete "HKCU\Software\Classes\CLSID\{86c…

2025年质量好的防火门厂家最新热销排行

2025年质量好的防火门厂家最新热销排行行业概述随着建筑安全标准的不断提高和消防法规的日益严格,防火门作为建筑消防安全的重要组成部分,其市场需求持续增长。2025年,防火门行业迎来了新一轮的技术革新和品质升级,…

2025年靠谱的武汉水沟钢模板厂家最新权威推荐排行榜

2025年靠谱的武汉水沟钢模板厂家最新权威推荐排行榜 在建筑工程领域,钢模板的质量和供货能力直接影响施工进度和工程质量。武汉作为华中地区的工业重镇,拥有众多钢模板生产厂家,但如何选择一家靠谱的供应商成为许多…

2025年正规的抗菌墙布最新TOP品牌厂家排行

2025年正规的抗菌墙布最新TOP品牌厂家排行抗菌墙布行业概述随着人们对家居环境健康要求的不断提高,抗菌墙布作为功能性装饰材料正迎来爆发式增长。2025年,抗菌墙布市场已形成以环保性、抗菌效果和设计美学为核心竞争…