Java事务回滚案例如何触发

wen java案例 20

Java事务回滚触发的典型案例

运行时异常自动回滚案例

@Service
public class OrderService {
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private InventoryService inventoryService;
    @Transactional
    public void createOrder(Order order) {
        // 1. 保存订单
        orderRepository.save(order);
        // 2. 扣减库存 - 如果这里抛出运行时异常,订单保存也会回滚
        inventoryService.deductStock(order.getProductId(), order.getQuantity());
        // 3. 模拟业务异常
        if (order.getAmount() > 10000) {
            throw new RuntimeException("订单金额超过限制");
        }
    }
}

检查型异常不会自动回滚

@Service
public class PaymentService {
    @Transactional
    public void processPayment(Payment payment) throws Exception {
        // 1. 扣款
        deductFromAccount(payment.getAccountId(), payment.getAmount());
        // 2. 这个检查型异常不会触发回滚!
        if (payment.getAmount() > 5000) {
            throw new Exception("大额支付需要审核");
        }
    }
    // 正确做法:包装成运行时异常或指定rollbackFor
    @Transactional(rollbackFor = Exception.class)
    public void processPayment2(Payment payment) throws Exception {
        // 扣款操作
        deductFromAccount(payment.getAccountId(), payment.getAmount());
        if (payment.getAmount() > 5000) {
            throw new Exception("大额支付需要审核");
        }
    }
}

嵌套事务回滚案例

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private LogService logService;
    @Transactional
    public void registerUser(User user) {
        // 1. 保存用户
        userRepository.save(user);
        // 2. 记录日志 - 事务传播行为REQUIRES_NEW
        try {
            logService.saveLog("用户注册: " + user.getName());
        } catch (Exception e) {
            // 日志失败不影响用户注册
            System.out.println("日志记录失败,但用户注册成功");
        }
        // 3. 发送欢迎邮件
        sendWelcomeEmail(user);
    }
}
@Service
public class LogService {
    @Autowired
    private LogRepository logRepository;
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void saveLog(String message) {
        logRepository.save(new Log(message));
        // 模拟日志保存失败
        if (message.contains("错误")) {
            throw new RuntimeException("日志保存异常");
        }
    }
}

编程式事务回滚

@Service
public class AccountService {
    @Autowired
    private PlatformTransactionManager transactionManager;
    @Autowired
    private AccountRepository accountRepository;
    public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
        // 定义事务
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
        TransactionStatus status = transactionManager.getTransaction(def);
        try {
            // 1. 扣款
            Account fromAccount = accountRepository.findById(fromId).orElseThrow();
            fromAccount.setBalance(fromAccount.getBalance().subtract(amount));
            accountRepository.save(fromAccount);
            // 2. 检查余额
            if (fromAccount.getBalance().compareTo(BigDecimal.ZERO) < 0) {
                throw new RuntimeException("余额不足");
            }
            // 3. 入账
            Account toAccount = accountRepository.findById(toId).orElseThrow();
            toAccount.setBalance(toAccount.getBalance().add(amount));
            accountRepository.save(toAccount);
            // 提交事务
            transactionManager.commit(status);
        } catch (RuntimeException e) {
            // 回滚事务
            transactionManager.rollback(status);
            throw e;
        } catch (Exception e) {
            // 回滚事务
            transactionManager.rollback(status);
            throw new RuntimeException("转账失败", e);
        }
    }
}

使用TransactionAspectSupport手动回滚

@Service
public class DocumentService {
    @Transactional
    public void uploadDocument(Document doc) {
        // 1. 保存文档
        documentRepository.save(doc);
        // 2. 上传到文件服务器
        boolean uploadSuccess = fileService.upload(doc.getContent(), doc.getPath());
        if (!uploadSuccess) {
            // 手动回滚,同时保留异常信息
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new RuntimeException("文件上传失败,事务回滚");
        }
        // 3. 更新文档状态
        doc.setStatus("UPLOADED");
        documentRepository.save(doc);
    }
}

常见的触发回滚场景

@Service
public class BatchProcessService {
    @Transactional
    public void batchUpdate(List<Entity> entities) {
        for (int i = 0; i < entities.size(); i++) {
            Entity entity = entities.get(i);
            try {
                // 处理每个实体
                processSingleEntity(entity);
            } catch (DataIntegrityViolationException e) {
                // 数据完整性违规 - 自动回滚
                throw e;
            } catch (OptimisticLockException e) {
                // 乐观锁异常 - 自动回滚
                throw e;
            } catch (Exception e) {
                // 处理单个失败,不影响其他
                log.error("处理第{}个实体失败: {}", i, e.getMessage());
            }
        }
    }
    private void processSingleEntity(Entity entity) {
        // 可能抛出各种异常
    }
}
  1. 默认行为:只有RuntimeExceptionError及其子类会触发回滚
  2. 检查型异常:默认不回滚,需通过rollbackFor指定
  3. 嵌套事务REQUIRES_NEW会暂停当前事务,独立异常不影响外层
  4. 手动回滚:使用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()
  5. 编程式事务:通过PlatformTransactionManager精确控制

这些案例覆盖了实际开发中最常见的事务回滚场景。

Java事务回滚案例如何触发

抱歉,评论功能暂时关闭!