一、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()失败时所有嵌套操作回滚