Spring事物

文章目录

大家好,今天想和大家分享一下Spring框架中的事务管理。这东西在实际开发中超级实用,尤其是处理数据库操作的时候,能帮我们避免很多坑。

为什么需要事务管理?

首先,事务就是一组操作,要么全成功,要么全失败。比如你转账,从A账户扣钱,再给B账户加钱,这两个步骤必须一起完成,要是扣钱成功了加钱失败,那不就乱套了?在Spring里,事务管理主要针对数据库操作,但也能扩展到其他资源。Spring提供了两种方式:编程式事务声明式事务。编程式就是手动写代码控制事务开始、提交、回滚;声明式更方便,通过注解或XML配置,让Spring自动帮你管。

Spring事务的核心概念

1. 事务传播行为

传播行为决定了事务在方法嵌套调用时的行为。Spring定义了7种:

传播行为 描述
REQUIRED 如果当前有事务,就加入;没有就新建一个。最常用。
REQUIRES_NEW 总是新建一个事务,挂起当前事务。
NESTED 嵌套事务,类似于REQUIRES_NEW,但回滚时只影响子事务。
SUPPORTS 有事务就加入,没有就非事务执行。
MANDATORY 必须有事务,否则抛异常。
NOT_SUPPORTED 非事务执行,如果有就挂起。
NEVER 必须非事务,否则抛异常。

2. 隔离级别

Spring支持数据库的隔离级别:

隔离级别 描述
DEFAULT 用数据库默认的。
READ_UNCOMMITTED 最低级别,可能脏读。
READ_COMMITTED 避免脏读,但可能不可重复读。
REPEATABLE_READ 避免不可重复读,但可能幻读。
SERIALIZABLE 最高级别,完全串行,但性能差。

实际项目中,READ_COMMITTED够用了,除非有特殊需求。

3. 回滚规则

默认情况下,Spring只在RuntimeException 时回滚,Checked Exception不会。你可以用@Transactional(rollbackFor = Exception.class)指定回滚的异常类型。

如何配置Spring事务?

Spring Boot时代,配置超级简单。主要用注解方式。

使用@Transactional注解

在Service方法上加:

java 复制代码
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class)
    public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
        User from = userRepository.findById(fromId).orElseThrow();
        User to = userRepository.findById(toId).orElseThrow();

        from.setBalance(from.getBalance().subtract(amount));
        to.setBalance(to.getBalance().add(amount));

        userRepository.save(from);
        userRepository.save(to);

        // 模拟异常
        int i = 10 / 0;
    }
}

这个例子中,如果抛异常,整个转账操作都会回滚。

事务失效的常见场景

1. 方法不是public的

Spring的事务是基于AOP代理实现的,默认只对public方法生效。如果你把@Transactional加在protected、private或package-private方法上,事务不会触发。

2. 同一个类内部方法调用

假如类A有方法foo()调用bar(),bar()有@Transactional,但因为没走代理(直接this.bar()),事务不生效。

解决方案

  • 在同一个类中不要用到内部方法调用
  • AopContext.currentProxy()走代理,但需@EnableAspectJAutoProxy(exposeProxy = true)。

3. 异常被捕获没抛出

@Transactional默认只在抛出RuntimeException时回滚。如果你try-catch了异常,没再抛,事务就提交了。

4. 数据库不支持事务

数据库不支持事务:如MyISAM引擎,用InnoDB。

总结

我在这篇文章中分享了Spring事务管理的实用经验,从为什么需要事务入手,解释了它如何确保操作的原子性,比如转账场景。接着,我详细介绍了核心概念,包括传播行为和隔离级别的表格展示,以及回滚规则。然后,我展示了如何用@Transactional注解配置事务,并举了转账代码例子。最后,我列出了事务失效的常见坑,如非public方法和类内调用问题,希望能帮大家在开发中避开雷区,更高效地处理数据库操作。

相关推荐
夜晚中的人海9 分钟前
【C++】异常介绍
android·java·c++
Le1Yu40 分钟前
2025-9-28学习笔记
java·笔记·学习
C++chaofan1 小时前
项目中为AI添加对话记忆
java·数据结构·人工智能·redis·缓存·个人开发·caffeine
老华带你飞1 小时前
机电公司管理小程序|基于微信小程序的机电公司管理小程序设计与实现(源码+数据库+文档)
java·数据库·vue.js·spring boot·微信小程序·小程序·机电公司管理小程序
拾忆,想起1 小时前
AMQP协议深度解析:消息队列背后的通信魔法
java·开发语言·spring boot·后端·spring cloud
PH = 72 小时前
Spring Ai Alibaba开发指南
java·后端·spring
涛声依旧2 小时前
基于springBoot鲜花商城小程序
java·spring·微信小程序
尘埃不入你眼眸3 小时前
服务器安装Java与nginx与nacos
java·服务器·nginx
karry_k4 小时前
什么是Fork/Join?
java·后端
卷Java4 小时前
小程序前端功能更新说明
java·前端·spring boot·微信小程序·小程序·uni-app