Java回滚数据库案例

wen java案例 1

本文目录导读:

Java回滚数据库案例

  1. 基于JDBC的简单回滚(最基础)
  2. Spring JDBC 模板的回滚(Spring框架)
  3. 基于Spring + MyBatis的完整案例
  4. 编程式事务管理(Spring)
  5. 事务传播行为示例
  6. 配置文件示例(application.yml)
  7. 数据库表结构

在Java中实现数据库回滚主要有几种方式,我将通过几个典型案例来展示。

基于JDBC的简单回滚(最基础)

import java.sql.*;
public class JDBCRollbackExample {
    public static void main(String[] args) {
        Connection conn = null;
        try {
            // 1. 获取数据库连接
            conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/test", 
                "root", 
                "password"
            );
            // 2. 关闭自动提交,开启事务
            conn.setAutoCommit(false);
            // 3. 执行多条SQL语句
            Statement stmt = conn.createStatement();
            // 模拟两个操作
            stmt.executeUpdate("INSERT INTO users (name, age) VALUES ('张三', 25)");
            // 故意制造一个错误
            int result = 1 / 0; // 这里会抛出异常
            stmt.executeUpdate("INSERT INTO users (name, age) VALUES ('李四', 30)");
            // 4. 所有操作成功,提交事务
            conn.commit();
            System.out.println("事务提交成功!");
        } catch (Exception e) {
            // 5. 发生异常,回滚事务
            if (conn != null) {
                try {
                    conn.rollback();
                    System.out.println("事务已回滚!");
                } catch (SQLException ex) {
                    ex.printStackTrace();
                }
            }
            e.printStackTrace();
        } finally {
            // 6. 关闭连接
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

Spring JDBC 模板的回滚(Spring框架)

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class UserService {
    @Resource
    private JdbcTemplate jdbcTemplate;
    @Transactional(rollbackFor = Exception.class)
    public void transferMoney(Long fromUserId, Long toUserId, Double amount) {
        // 1. 扣款操作
        String deductSql = "UPDATE accounts SET balance = balance - ? WHERE user_id = ?";
        jdbcTemplate.update(deductSql, amount, fromUserId);
        // 模拟一个异常
        if (fromUserId.equals(toUserId)) {
            throw new RuntimeException("不能转账给自己!");
        }
        // 2. 加款操作
        String addSql = "UPDATE accounts SET balance = balance + ? WHERE user_id = ?";
        jdbcTemplate.update(addSql, amount, toUserId);
        // 如果以上任何一步出错,整个事务都会回滚
        System.out.println("转账成功!");
    }
}

基于Spring + MyBatis的完整案例

// 实体类
public class Account {
    private Long id;
    private String name;
    private Double balance;
    // getter和setter方法
}
// Mapper接口
@Mapper
public interface AccountMapper {
    @Update("UPDATE account SET balance = balance - #{amount} WHERE id = #{id}")
    int deductBalance(@Param("id") Long id, @Param("amount") Double amount);
    @Update("UPDATE account SET balance = balance + #{amount} WHERE id = #{id}")
    int addBalance(@Param("id") Long id, @Param("amount") Double amount);
}
// Service实现类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountMapper accountMapper;
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void transfer(Long fromId, Long toId, Double amount) {
        // 1. 校验余额是否充足
        Account fromAccount = accountMapper.findById(fromId);
        if (fromAccount.getBalance() < amount) {
            throw new BusinessException("余额不足");
        }
        // 2. 扣款
        int rows = accountMapper.deductBalance(fromId, amount);
        if (rows == 0) {
            throw new BusinessException("扣款失败");
        }
        // 模拟一个运行时异常
        if (amount <= 0) {
            throw new IllegalArgumentException("转账金额必须大于0");
        }
        // 3. 加款
        rows = accountMapper.addBalance(toId, amount);
        if (rows == 0) {
            throw new BusinessException("加款失败");
        }
    }
}
// 自定义业务异常
public class BusinessException extends RuntimeException {
    public BusinessException(String message) {
        super(message);
    }
}

编程式事务管理(Spring)

import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
@Service
public class ProgrammaticTransactionService {
    @Autowired
    private PlatformTransactionManager transactionManager;
    public void businessLogic() {
        // 创建事务定义
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        // 开启事务
        TransactionStatus status = transactionManager.getTransaction(def);
        try {
            // 业务逻辑
            // ... 执行数据库操作
            // 提交事务
            transactionManager.commit(status);
            System.out.println("事务提交成功");
        } catch (Exception e) {
            // 回滚事务
            transactionManager.rollback(status);
            System.out.println("事务回滚成功");
            e.printStackTrace();
        }
    }
}

事务传播行为示例

@Service
public class TransactionPropagationExample {
    @Autowired
    private MethodA methodA;
    @Service
    public static class MethodA {
        @Transactional
        public void methodA() {
            // 数据库操作1
            insertData("A");
            try {
                methodB(); // 调用方法B
            } catch (Exception e) {
                // 即使方法B失败了,方法A的代码不会受影响(如果B使用REQUIRES_NEW)
            }
        }
        @Transactional(propagation = Propagation.REQUIRES_NEW) // 开启新事务
        public void methodB() {
            // 数据库操作2
            insertData("B");
            // 这里抛异常,只回滚方法B的事务
            if (true) {
                throw new RuntimeException("方法B的异常");
            }
        }
    }
}

配置文件示例(application.yml)

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: password
    driver-class-name: com.mysql.cj.jdbc.Driver
  # 事务管理器配置
  jpa:
    hibernate:
      ddl-auto: create-drop
  # 事务配置
  transaction:
    default-timeout: 30
# MyBatis配置
mybatis:
  configuration:
    map-underscore-to-camel-case: true

数据库表结构

-- 创建账户表
CREATE TABLE account (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    balance DECIMAL(10,2) NOT NULL DEFAULT 0
);
-- 创建用户表
CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    age INT NOT NULL
);
-- 创建账户明细表
CREATE TABLE account_transaction_log (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    from_account_id BIGINT NOT NULL,
    to_account_id BIGINT NOT NULL,
    amount DECIMAL(10,2),
    create_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
  1. JDBC层面:通过conn.setAutoCommit(false)关闭自动提交,手动控制commit()rollback()

  2. Spring注解方式

    • @Transactional 是最常用的方式
    • rollbackFor 指定哪些异常触发回滚
    • propagation 设置事务传播行为
  3. 事务特性

    • 原子性(Atomicity)
    • 一致性(Consistency)
    • 隔离性(Isolation)
    • 持久性(Durability)
  4. 最佳实践

    • 尽量使用声明式事务(@Transactional
    • 异常要设置正确的rollbackFor
    • 避免长事务
    • 注意事务的隔离级别

这个案例涵盖了从基础的JDBC到Spring框架的各种回滚实现方式,可以根据项目需求选择合适的方式。

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