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

Spring 框架@Transactional注解,事务的各个传播行为的逻辑以及使用场景。

Spring框架的@Transactional注解提供了丰富的事务传播行为配置。以下是各种传播行为的详细逻辑说明:

1. 传播行为概述

@Transactional(propagation = Propagation.REQUIRED)
public void someMethod() {// 方法逻辑
}

2. 7种传播行为详解

2.1 REQUIRED(默认)

逻辑:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。

@Service
public class UserService {@Transactional(propagation = Propagation.REQUIRED)public void methodA() {// 如果调用methodA时没有事务,则创建新事务// 如果调用methodA时已有事务,则加入该事务methodB(); // methodB会加入methodA的事务}@Transactional(propagation = Propagation.REQUIRED)public void methodB() {// 加入methodA的事务}
}

2.2 REQUIRES_NEW

逻辑:创建一个新的事务,如果当前存在事务,则把当前事务挂起。

@Service
public class OrderService {@Transactional(propagation = Propagation.REQUIRED)public void processOrder(Order order) {// 主事务orderRepository.save(order);try {auditService.logAction("ORDER_CREATED"); // 独立事务,不受主事务回滚影响} catch (Exception e) {// 审计日志失败不影响主事务}// 如果这里抛出异常,order会被回滚,但审计日志已提交}
}@Service
public class AuditService {@Transactional(propagation = Propagation.REQUIRES_NEW)public void logAction(String action) {// 总是创建新事务,挂起调用方的事务auditRepository.save(new AuditLog(action));// 即使调用方事务回滚,这个日志记录也会被提交}
}

2.3 SUPPORTS

逻辑:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务方式执行。

@Service
public class ProductService {@Transactional(propagation = Propagation.SUPPORTS)public Product getProduct(Long id) {// 如果调用方有事务,则加入事务// 如果调用方无事务,则非事务执行return productRepository.findById(id);}@Transactional(propagation = Propagation.REQUIRED)public void updateProduct(Product product) {// 有事务getProduct(product.getId()); // 加入当前事务productRepository.update(product);}
}

2.4 MANDATORY

逻辑:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。

@Service
public class AccountService {@Transactional(propagation = Propagation.MANDATORY)public void validateAccount(Account account) {// 必须在事务中调用,否则抛出IllegalTransactionStateExceptionif (account.getBalance() < 0) {throw new InsufficientBalanceException();}}@Transactional(propagation = Propagation.REQUIRED)public void transferMoney(Account from, Account to, BigDecimal amount) {// 有事务环境validateAccount(from); // 正常执行// 转账逻辑...}public void checkAccount(Account account) {validateAccount(account); // 抛出异常:没有事务}
}

2.5 NOT_SUPPORTED

逻辑:以非事务方式执行操作,如果当前存在事务,则把当前事务挂起。

@Service
public class ReportService {@Transactional(propagation = Propagation.NOT_SUPPORTED)public Report generateLargeReport() {// 总是非事务执行,即使调用方有事务也会被挂起// 适合耗时操作,避免长时间占用事务连接return reportGenerator.generate();}@Transactional(propagation = Propagation.REQUIRED)public void processData() {// 事务操作dataRepository.process();// 生成报表(非事务,不占用事务资源)Report report = generateLargeReport();// 继续事务操作dataRepository.finalizeProcess();}
}

2.6 NEVER

逻辑:以非事务方式执行,如果当前存在事务,则抛出异常。

@Service
public class CacheService {@Transactional(propagation = Propagation.NEVER)public void refreshCache() {// 必须在非事务环境下调用// 如果有事务存在,抛出IllegalTransactionStateExceptioncacheManager.refreshAll();}public void scheduledRefresh() {refreshCache(); // 正常执行(无事务环境)}@Transactionalpublic void updateAndRefresh() {updateData();refreshCache(); // 抛出异常:存在事务}
}

2.7 NESTED

逻辑:如果当前存在事务,则在嵌套事务内执行;如果当前没有事务,则创建新事务。

@Service
public class BatchService {@Transactional(propagation = Propagation.REQUIRED)public void processBatch(List<Item> items) {for (Item item : items) {try {processItem(item); // 嵌套事务} catch (Exception e) {// 单个item处理失败不影响其他itemlog.error("Item processing failed: " + item.getId(), e);}}}@Transactional(propagation = Propagation.NESTED)public void processItem(Item item) {// 嵌套事务:可以独立回滚而不影响外部事务itemRepository.save(item);inventoryService.updateStock(item);if (item.getQuantity() < 0) {throw new InvalidQuantityException(); // 只回滚这个item的处理}}
}

3. 实际应用场景

3.1 订单处理系统

@Service
public class OrderService {@Autowiredprivate InventoryService inventoryService;@Autowiredprivate AuditService auditService;@Transactional(propagation = Propagation.REQUIRED)public Order createOrder(Order order) {// 主事务开始// 1. 保存订单(在主事务中)orderRepository.save(order);// 2. 扣减库存(独立事务,即使订单失败库存扣减也生效)inventoryService.deductStock(order.getItems());// 3. 记录审计日志(独立事务,必须成功)auditService.logOrderCreation(order);// 4. 发送消息(非事务,不阻塞主事务)notificationService.sendConfirmation(order);return order;// 主事务提交}
}@Service
public class InventoryService {@Transactional(propagation = Propagation.REQUIRES_NEW)public void deductStock(List<OrderItem> items) {// 独立事务,不受订单事务回滚影响items.forEach(item -> {inventoryRepository.reduceStock(item.getProductId(), item.getQuantity());});}
}@Service
public class AuditService {@Transactional(propagation = Propagation.MANDATORY)public void logOrderCreation(Order order) {// 必须在事务中调用auditRepository.save(new AuditLog("ORDER_CREATED", order.getId()));}
}@Service
public class NotificationService {@Transactional(propagation = Propagation.NOT_SUPPORTED)public void sendConfirmation(Order order) {// 非事务执行,避免长时间占用数据库连接emailService.sendOrderConfirmation(order);}
}

3.2 异常处理示例

@Service
public class ComplexService {@Transactional(propagation = Propagation.REQUIRED)public void complexOperation() {try {// 主业务逻辑mainBusinessLogic();// 独立事务的辅助操作independentOperation();} catch (BusinessException e) {// 业务异常,回滚主事务throw e;} catch (AuxiliaryException e) {// 辅助操作异常,不影响主事务log.error("Auxiliary operation failed", e);}}@Transactional(propagation = Propagation.REQUIRES_NEW)public void independentOperation() {// 这个操作失败不会影响complexOperation的主事务auxiliaryService.process();}
}

4. 传播行为选择指南

传播行为适用场景注意事项
REQUIRED大多数业务方法默认选择,简单可靠
REQUIRES_NEW需要独立提交的操作(如日志、消息)注意数据库连接资源
NESTED批量处理中的单个项目需要数据库支持保存点
SUPPORTS查询方法可根据调用方决定是否事务
MANDATORY必须在事务中调用的方法强制事务环境
NOT_SUPPORTED耗时操作、外部系统调用避免长时间占用事务
NEVER不应该在事务中调用的方法强制非事务环境

5. 重要注意事项

  1. 自调用问题:同一个类中的方法调用不会经过AOP代理
  2. 异常处理:默认只对RuntimeException回滚,可通过rollbackFor配置
  3. 超时设置:长时间事务需要设置超时时间
  4. 只读事务:查询操作可设置readOnly = true优化性能

理解这些传播行为的逻辑对于设计正确的事务边界和保证数据一致性至关重要。

http://www.dtcms.com/a/478041.html

相关文章:

  • 福建巢网站建设chinacd小说wordpress
  • 轻松搭建RTMP推流、WebRTC拉流服务器SRS服务,源码编译安装
  • Linux内核架构浅谈26-Linux实时进程调度:优先级反转与解决方案
  • 企业官方网站建设目的网站基础知识
  • 天水市建设局企业注册网站紧急访问升级狼人通知
  • 计算机视觉进阶教学之颜色识别
  • 实战任务二:用扣子空间通过任务提示词制作精美PPT
  • 【Docker】13、Docker安装RustFS服务
  • 什么是 Web3 品牌?
  • 指纹技术深度剖析:从原理到实践的全方位探索
  • 在 MySQL 中,当使用 SUM() 函数对某列进行求和时,如果没有符合条件的记录(即查询结果为空),SUM() 会返回 NULL
  • 公司全场景运营中 PPT 的类型、功能与作用详解
  • WHAT - SQLite 数据库
  • 网站开发 工程师 类型电商网站文档
  • 框架--Swagger
  • 网站设计的基本步骤有意思的网站
  • Ethernaut Level 10: Re-entrancy - 经典重入攻击详解
  • 维星AI GEO优化:AI搜索引擎时代,企业如何抢占流量C位?
  • 京东pc网站用什么做的php编程语言
  • STM32 单片机ADC 使用内部电压基准
  • 从美团到朴朴、我店与远方好物:本地生活的四种演化路径与未来趋势
  • U盘白名单管控工具(可以添加U盘ID无法实现白名单效果)
  • 【仿真测试】基于FPGA的完整DQPSK通信链路实现,含频偏锁定,帧同步,定时点,Viterbi译码,信道,误码统计
  • 网站开发推荐资料柯城区住房和城乡建设局网站
  • 算法沉淀第一天(Triple Removal)
  • PGLRNet论文笔记
  • 如何利用docker部署springboot应用
  • 前端学习3:学习时间:40分钟
  • 网站建设主页文档互联网网站运营推广
  • 七台河网站网站建设做网站有什么意义