Spring Boot 事务管理完整教程

一、注解事务(声明式事务)

1. 基础配置

java 复制代码
// 启动类添加注解
@SpringBootApplication
@EnableTransactionManagement  // 通常默认开启,可省略
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

2. 使用 @Transactional

java 复制代码
@Service
public class UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    // 基本用法
    @Transactional
    public void createUser(User user) {
        userMapper.insert(user);
        // 发生异常自动回滚
    }
    
    // 指定回滚异常
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(User user) throws Exception {
        userMapper.update(user);
        if (user.getAge() < 0) {
            throw new Exception("年龄不能为负数");
        }
    }
    
    // 不回滚指定异常
    @Transactional(noRollbackFor = NullPointerException.class)
    public void deleteUser(Long id) {
        userMapper.delete(id);
        if (id == null) {
            throw new NullPointerException(); // 不会回滚
        }
    }
    
    // 设置事务传播行为
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void saveLog(Log log) {
        // 新开事务,不受外层影响
        logMapper.insert(log);
    }
    
    // 设置超时和只读
    @Transactional(timeout = 30, readOnly = true)
    public List<User> findAllUsers() {
        return userMapper.selectAll();
    }
    
    // 隔离级别
    @Transactional(isolation = Isolation.READ_COMMITTED)
    public User getUserById(Long id) {
        return userMapper.selectById(id);
    }
}

3. 常见传播行为

传播行为 说明
REQUIRED 默认,有事务则加入,无则新建
REQUIRES_NEW 挂起当前事务,新建事务
SUPPORTS 有事务则加入,无则非事务执行
NOT_SUPPORTED 非事务执行,挂起当前事务
MANDATORY 必须有事务,否则抛异常
NEVER 必须非事务,有事务则抛异常
NESTED 嵌套事务(Savepoint机制)

4. 注意事项

java 复制代码
// ❌ 错误:内部调用不生效
@Service
public class ServiceA {
    @Transactional
    public void methodA() {
        methodB();  // @Transactional 不生效!
    }
    
    @Transactional
    public void methodB() {}
}

// ✅ 正确:通过代理调用
@Service
public class ServiceA {
    @Autowired
    private ServiceA self;  // 注入自身代理
    
    @Transactional
    public void methodA() {
        self.methodB();  // 生效
    }
    
    @Transactional
    public void methodB() {}
}

二、手动事务(编程式事务)

方式1:TransactionTemplate(推荐)

java 复制代码
@Service
public class OrderService {
    
    @Autowired
    private TransactionTemplate transactionTemplate;
    
    @Autowired
    private OrderMapper orderMapper;
    
    public void createOrder(Order order) {
        transactionTemplate.execute(status -> {
            try {
                orderMapper.insert(order);
                orderMapper.updateStock(order.getProductId());
                return order.getId();
            } catch (Exception e) {
                status.setRollbackOnly();  // 标记回滚
                throw new RuntimeException("创建订单失败", e);
            }
        });
    }
    
    // 配置事务属性
    @Bean
    public TransactionTemplate transactionTemplate(PlatformTransactionManager manager) {
        TransactionTemplate template = new TransactionTemplate(manager);
        template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        template.setTimeout(30);
        return template;
    }
    
    // 复杂业务处理
    public Result processOrder(Order order) {
        return transactionTemplate.execute(status -> {
            try {
                // 业务逻辑1
                orderMapper.insert(order);
                
                // 条件判断手动回滚
                if (order.getAmount() < 0) {
                    status.setRollbackOnly();
                    return Result.fail("金额无效");
                }
                
                // 业务逻辑2
                paymentService.pay(order);
                
                return Result.success();
            } catch (Exception e) {
                status.setRollbackOnly();
                return Result.fail(e.getMessage());
            }
        });
    }
}

方式2:PlatformTransactionManager

java 复制代码
@Service
public class PaymentService {
    
    @Autowired
    private PlatformTransactionManager transactionManager;
    
    @Autowired
    private AccountMapper accountMapper;
    
    public void transfer(Long fromId, Long toId, BigDecimal amount) {
        // 1. 定义事务属性
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        def.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
        
        // 2. 获取事务状态
        TransactionStatus status = transactionManager.getTransaction(def);
        
        try {
            // 扣款
            accountMapper.decreaseBalance(fromId, amount);
            // 加款
            accountMapper.increaseBalance(toId, amount);
            
            // 提交
            transactionManager.commit(status);
        } catch (Exception e) {
            // 回滚
            transactionManager.rollback(status);
            throw new RuntimeException("转账失败", e);
        }
    }
    
    // 嵌套事务示例
    public void complexBusiness() {
        // 外层事务
        DefaultTransactionDefinition outerDef = new DefaultTransactionDefinition();
        TransactionStatus outerStatus = transactionManager.getTransaction(outerDef);
        
        try {
            // 业务A
            doBusinessA();
            
            // 内层独立事务
            DefaultTransactionDefinition innerDef = new DefaultTransactionDefinition();
            innerDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
            TransactionStatus innerStatus = transactionManager.getTransaction(innerDef);
            try {
                doBusinessB();
                transactionManager.commit(innerStatus);
            } catch (Exception e) {
                transactionManager.rollback(innerStatus);
                // 内层失败不影响外层
            }
            
            transactionManager.commit(outerStatus);
        } catch (Exception e) {
            transactionManager.rollback(outerStatus);
            throw new RuntimeException("业务失败", e);
        }
    }
}

三、完整示例:用户注册+发送通知

java 复制代码
@Service
public class RegisterService {
    
    @Autowired
    private TransactionTemplate transactionTemplate;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private NotificationService notificationService;
    
    // 组合使用
    public void register(User user) {
        // 主事务:用户注册
        Long userId = transactionTemplate.execute(status -> {
            try {
                // 保存用户
                userMapper.insert(user);
                
                // 初始化账户
                accountService.initAccount(user.getId());
                
                return user.getId();
            } catch (DuplicateKeyException e) {
                status.setRollbackOnly();
                throw new BusinessException("用户名已存在");
            }
        });
        
        // 非事务:发送通知(失败不影响注册)
        try {
            notificationService.sendWelcomeEmail(user.getEmail());
        } catch (Exception e) {
            log.error("发送邮件失败", e);
        }
    }
    
    // 混合使用
    @Transactional
    public void registerWithCoupon(User user, Coupon coupon) {
        // 声明式事务
        userMapper.insert(user);
        
        // 手动事务:发放优惠券(独立事务)
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        transactionTemplate.execute(status -> {
            try {
                couponService.giveCoupon(user.getId(), coupon);
                return true;
            } catch (Exception e) {
                log.error("发放优惠券失败", e);
                status.setRollbackOnly();
                return false;
            }
        });
        
        // 注册失败不影响优惠券发放
        if (user.getAge() < 0) {
            throw new IllegalArgumentException("年龄无效");
        }
    }
}

四、配置详解

bash 复制代码
# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test
    username: root
    password: 123456
    
  # 事务配置
  transaction:
    default-timeout: 30  # 默认超时时间
    rollback-on-commit-failure: true  # 提交失败回滚
java 复制代码
@Configuration
public class TransactionConfig {
    
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
    
    @Bean
    public TransactionTemplate transactionTemplate(PlatformTransactionManager manager) {
        return new TransactionTemplate(manager);
    }
    
    // 配置多数据源事务
    @Bean
    public PlatformTransactionManager masterTransactionManager(@Qualifier("masterDataSource") DataSource ds) {
        return new DataSourceTransactionManager(ds);
    }
    
    @Bean
    public PlatformTransactionManager slaveTransactionManager(@Qualifier("slaveDataSource") DataSource ds) {
        return new DataSourceTransactionManager(ds);
    }
}

五、选择建议

场景 推荐方式
简单CRUD @Transactional
复杂业务逻辑 TransactionTemplate
需要细粒度控制 PlatformTransactionManager
多数据源 手动指定事务管理器
测试环境 @Transactional + @Rollback

六、常见问题

java 复制代码
// 1. 事务不生效:方法必须是public
@Transactional  // private 不生效
private void method() {}

// 2. 异常被捕获不抛出不回滚
@Transactional
public void method() {
    try {
        // 业务
    } catch (Exception e) {
        // 不抛出 -> 不回滚,需要手动回滚
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
}

// 3. 默认只回滚RuntimeException,需要指定
@Transactional(rollbackFor = Exception.class)

以上涵盖了Spring Boot中事务的主要使用方式,建议优先使用@Transactional,需要更灵活控制时使用TransactionTemplate。

相关推荐
学长毕设21 分钟前
基于springboot的食品仓库管理系统
java·spring boot·后端
时间售卖铺1 小时前
触发器与函数实战:MySQL高效编程秘诀
运维·数据库·mysql·云原生
qetfw1 小时前
UOS MariaDB 数据库:安装、最小权限与备份验证
linux·数据库·mariadb·uos
步行cgn1 小时前
FormHttpMessageConverter 详解:Spring MVC 中表单数据的读写转换器
java·spring·mvc
龙亘川1 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
金銀銅鐵1 小时前
[Java] 用 CLI 展示 EnumMap 增删键值对时的内部变化
java·源码·ai编程
秋天的怀念_David1 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Raas1002 小时前
AI网关部署方案?从部署到上线全流程
java·开发语言·人工智能·gateway·ai网关·企业级ai网关·企业级ai产品
数智园区合作社2 小时前
问数平台怎么把同一个指标锁成一个数
大数据·数据库·人工智能·ai
lbb 小魔仙2 小时前
Windows搭建PaddleOCR+飞书Webhook自动打卡通知机器人:识别、推送与远程触发完整教程
数据库·人工智能·prometheus·时序数据库