Java案例如何实现回滚?

wen python案例 4

本文目录导读:

Java案例如何实现回滚?

  1. Spring声明式事务(最常用)
  2. JDBC事务管理
  3. Spring编程式事务管理
  4. 自定义回滚逻辑(补偿机制)
  5. 配置注意事项
  6. 最佳实践

在Java中实现回滚主要有以下几种方式,具体取决于你使用的技术栈:

Spring声明式事务(最常用)

使用 @Transactional 注解

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private AccountRepository accountRepository;
    @Transactional(rollbackFor = Exception.class) // 指定回滚异常类型
    public void createUserAndAccount(User user, Account account) {
        // 第一个操作
        userRepository.save(user);
        // 如果这里发生异常,第一个操作会自动回滚
        if (user.getAge() < 0) {
            throw new IllegalArgumentException("Age cannot be negative");
        }
        // 第二个操作
        accountRepository.save(account);
    }
}

手动控制回滚

@Service
public class OrderService {
    @Transactional
    public void createOrder(Order order) {
        try {
            // 执行业务逻辑
            saveOrder(order);
            updateInventory(order);
            deductBalance(order);
        } catch (Exception e) {
            // 手动触发回滚
            TransactionAspectSupport.currentTransactionStatus()
                .setRollbackOnly();
            throw e;
        }
    }
}

JDBC事务管理

原生JDBC实现

public class JdbcTransactionDemo {
    public void transferMoney(Connection conn, 
                              int fromAccount, 
                              int toAccount, 
                              double amount) throws SQLException {
        conn.setAutoCommit(false); // 关闭自动提交
        try {
            // 扣款操作
            String debitSql = "UPDATE accounts SET balance = balance - ? WHERE id = ?";
            try (PreparedStatement pstmt = conn.prepareStatement(debitSql)) {
                pstmt.setDouble(1, amount);
                pstmt.setInt(2, fromAccount);
                pstmt.executeUpdate();
            }
            // 如果余额不足,抛异常触发回滚
            if (checkBalance(conn, fromAccount) < 0) {
                throw new SQLException("Insufficient balance");
            }
            // 存款操作
            String creditSql = "UPDATE accounts SET balance = balance + ? WHERE id = ?";
            try (PreparedStatement pstmt = conn.prepareStatement(creditSql)) {
                pstmt.setDouble(1, amount);
                pstmt.setInt(2, toAccount);
                pstmt.executeUpdate();
            }
            // 提交事务
            conn.commit();
        } catch (SQLException e) {
            // 发生异常时回滚
            conn.rollback();
            throw e;
        } finally {
            conn.setAutoCommit(true); // 恢复自动提交
        }
    }
    private double checkBalance(Connection conn, int accountId) throws SQLException {
        // 查询余额的逻辑
        return 1000.0; // 简化示例
    }
}

Spring编程式事务管理

@Service
public class TransactionTemplateDemo {
    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    private SomeRepository repository;
    public void doComplexOperation() {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    // 业务操作1
                    repository.saveEntity1(entity1);
                    // 业务操作2(可能失败)
                    repository.saveEntity2(entity2);
                } catch (Exception e) {
                    // 设置事务回滚
                    status.setRollbackOnly();
                    throw e;
                }
            }
        });
    }
}

自定义回滚逻辑(补偿机制)

适用于分布式系统或无法使用数据库事务的场景:

@Component
public class CompensatingTransactionDemo {
    @Autowired
    private ServiceA serviceA;
    @Autowired
    private ServiceB serviceB;
    public void executeWithCompensation() {
        boolean stepASuccess = false;
        boolean stepBSuccess = false;
        try {
            // 执行步骤A
            serviceA.doStepA();
            stepASuccess = true;
            // 执行步骤B
            serviceB.doStepB();
            stepBSuccess = true;
        } catch (Exception e) {
            log.error("Operation failed, starting compensation...");
            // 执行补偿操作
            if (stepASuccess) {
                compensateStepA();
            }
            if (stepBSuccess) {
                compensateStepB();
            }
            throw new RuntimeException("Transaction failed, compensated", e);
        }
    }
    private void compensateStepA() {
        serviceA.undoStepA();
    }
    private void compensateStepB() {
        serviceB.undoStepB();
    }
}

配置注意事项

Spring Boot 配置

spring:
  datasource:
    # 数据源配置
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: password
  # 事务管理配置
  transaction:
    rollback-on-commit-failure: true
    default-timeout: 30

@Transactional 注解的关键属性

@Transactional(
    propagation = Propagation.REQUIRED,  // 事务传播行为
    isolation = Isolation.READ_COMMITTED, // 隔离级别
    timeout = 30,                         // 超时时间(秒)
    rollbackFor = {Exception.class, RuntimeException.class},  // 触发回滚的异常
    noRollbackFor = {BusinessException.class}  // 不触发回滚的异常
)

最佳实践

  1. 选择合适的回滚策略

    • 单体应用:使用声明式事务
    • 分布式系统:使用Saga模式或补偿事务
  2. 明确回滚范围

    @Transactional(rollbackFor = Exception.class)
    // 默认只回滚RuntimeException,这里设置回滚所有异常
  3. 避免在事务中捕获异常

    // ❌ 错误示例:捕获了异常导致不回滚
    @Transactional
    public void badExample() {
        try {
            saveData();
        } catch (Exception e) {
            log.error("Error", e); // 异常被吃掉,事务不会回滚
        }
    }
    // ✅ 正确示例:让异常传播出去
    @Transactional
    public void goodExample() {
        saveData();
    }
  4. 数据库引擎选择

    • MySQL使用InnoDB(支持事务)
    • 避免使用MyISAM(不支持事务)

选择合适的回滚方式取决于你的应用架构、数据一致性要求以及是否支持分布式事务。

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