Spring事务传播机制

一、Spring事务七种传播行为

在这里插入图片描述

二、代码示例

1.REQUIRED (默认)

@Service
public class OrderService {
    @Autowired
    private InventoryService inventoryService;
    
    @Transactional  // 默认REQUIRED
    public void createOrder(Order order) {
        // 主业务逻辑
        orderDao.save(order);
        inventoryService.deductStock(order); // 调用子方法
    }
}

@Service
public class InventoryService {
    @Transactional(propagation = Propagation.REQUIRED) // 加入主事务
    public void deductStock(Order order) {
        // 扣减库存逻辑
    }
}
// 当createOrder()调用deductStock()时:
// - 若createOrder有事务:deductStock加入该事务
// - 若createOrder无事务:deductStock创建新事务

在代码中

  • deductStock(Order order)回滚createOrder(Order order)也会进行回滚。
  • createOrder(Order order)回滚deductStock(Order order)也会回滚。

2.SUPPORTS

@Service
public class ReportService {
    @Transactional(propagation = Propagation.SUPPORTS)
    public Report generateReport() {
        // 报表查询(可运行在事务中,但非必需)
        return reportDao.getData();
    }
}

// 调用场景:
// 1. 在@Transactional方法内调用:使用现有事务
// 2. 直接调用:非事务执行

3.MANDATORY

强制性的必须在事务中调用不在事务中调用直接抛出异常

@Service
public class PaymentService {
    @Transactional(propagation = Propagation.MANDATORY) // 强制要求事务
    public void processPayment(Payment payment) {
        if(payment == null) throw new IllegalArgumentException();
        paymentDao.save(payment);
    }
}

// 调用时:
// - 在事务方法中调用:正常执行
// - 在非事务方法中调用:抛出TransactionRequiredException

4.REQUIRES_NEW

@Service
public class AuditService {
    @Transactional(propagation = Propagation.REQUIRES_NEW) // 始终新事务
    public void logOperation(String action) {
        auditLogDao.save(new AuditLog(action));
    }
}

@Service
public class UserService {
    @Transactional
    public void updateUser(User user) {
        try {
            userDao.update(user);
            auditService.logOperation("UPDATE_USER"); // 独立事务
        } catch (Exception e) {
            // 即使此处回滚,日志记录仍会提交
        }
    }
}
// 日志记录不受主事务回滚影响

不管有没有事务都要开启一个新事务,并且两个事务不会相互影响。

  • logOperation(String action)回滚不会导致updateUser(User user)回滚。
  • updateUser(User user)回滚不会导致logOperation(String action)回滚。

5.NOT_SUPPORTED

以非事务运行,如果当前存在事务就把当前事务挂起

@Service
public class ExternalService {
    @Transactional(propagation = Propagation.NOT_SUPPORTED) // 强制非事务
    public void callLegacySystem() {
        // 调用不支持事务的旧系统
        legacyClient.invoke();
    }
}

// 在事务方法中调用时:
// 1. 挂起当前事务
// 2. 非事务执行callLegacySystem()
// 3. 恢复原事务

6. NEVER

以非事务运行,如果存在事务则报错

@Service
public class CacheService {
    @Transactional(propagation = Propagation.NEVER) // 禁止在事务中调用
    public void refreshCache() {
        // 敏感操作(如直接内存操作)
        cache.clearAll();
    }
}

// 在@Transactional方法中调用refreshCache()将抛出:
// IllegalTransactionStateException

7. NESTED

@Service
public class BatchService {
    @Transactional
    public void processBatch(List<Item> items) {
        for(Item item : items) {
            try {
                processItem(item); // 嵌套事务
            } catch (Exception e) {
                // 单个失败不影响整体批次
            }
        }
    }

    @Transactional(propagation = Propagation.NESTED) // 嵌套事务
    public void processItem(Item item) {
        itemDao.process(item);
        if(item.isInvalid()) {
            throw new ValidationException(); // 回滚到保存点
        }
    }
}
// 说明:
// - processItem()失败时回滚到保存点,继续处理其他item
// - processBatch()失败时所有嵌套操作回滚
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值