SpringBoot事务

本文详细介绍了SpringBoot中的事务特性,包括传播行为、隔离级别、超时设置、只读模式以及处理事务失效场景的方法,如未被Spring托管的方法调用、异常处理策略和多线程问题等。
摘要由CSDN通过智能技术生成

一、SpringBoot特性

1、传播行为(Propagation)

控制事务方法的执行方式,例如是否加入已存在的事务、新建一个事务等。

REQUIRED:支持当前事务,如果不存在则新建事务。

SUPPORTS:支持当前事务,如果不存在则以非事务方式执行。

MANDATORY:支持当前事务,如果不存在则抛出异常。

REQUIRES_NEW:新建事务,如果当前存在事务,则挂起当前事务。

NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则挂起当前事务。

NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。

NESTED:如果当前存在事务,则在嵌套事务内执行。如果不存在事务,则新建事务。

2、隔离级别(Isolation)

控制事务的隔离程度,用于处理多个事务同时操作相同数据时可能出现的问题。

DEFAULT:使用默认的隔离级别。

READ_UNCOMMITTED:允许读取未提交的数据更改。

READ_COMMITTED:只能读取已提交的数据。

REPEATABLE_READ:可重复读取数据,即在同一事务内多次读取数据结果保持一致。

SERIALIZABLE:最高隔离级别,确保不会出现脏读、不可重复读和幻读。

3、超时(Timeout)

设置事务超时时间,如果事务在指定时间内没有完成,则自动回滚。

timeout = 30:设置事务超时时间为 30 秒。

4、只读(ReadOnly)

设置事务是否为只读,只读事务可以优化事务处理性能。

readOnly = true:设置事务为只读。

5、回滚规则(RollbackRules)

设置事务回滚的规则,可以根据异常类型进行回滚。

rollbackFor = {SQLException.class, RuntimeException.class}:设置遇到 SQLException 和 RuntimeException 异常时回滚事务。


二、事务失效场景

1、未被 Spring 托管的方法调用

如果一个事务方法内部调用了另一个对象的非 public 方法,或者调用了同一个对象内部的另一个 @Transactional 方法,事务可能会失效。

解决方案

避免在事务方法内调用非 public 方法。

将调用的方法提取到一个 Spring 托管的 Bean 中,并通过依赖注入的方式调用。

如果无法将方法提取到 Spring Bean 中,可以考虑手动获取当前 Spring 上下文,并使用上下文对象调用方法。但这种方法不推荐,因为绕过了 Spring 的事务管理。

2、异常被捕获而不重新抛出

 如果在事务方法内捕获了异常并处理,但没有重新抛出异常,事务将无法正确回滚。

解决方案

确保异常被正确地重新抛出以触发事务回滚。

当在事务方法内捕获了异常并处理后,如果不重新抛出异常,事务将无法正确回滚。这是因为 Spring 事务管理默认只会捕获抛出的异常来触发事务回滚。如果异常被捕获并在方法内部处理后,事务管理器无法检测到异常,因此无法触发事务回滚。

要解决这个问题,可以考虑以下方案:

重新抛出异常: 在捕获到异常后,通过 throw 关键字将异常重新抛出。这样可以让事务管理器捕获到异常,从而触发事务回滚。

@Transactional
public void transactionalMethod() {
    try {
        // 业务逻辑
    } catch (Exception e) {
        // 处理异常
        throw e; // 重新抛出异常
    }
}

手动标记回滚: 如果捕获到异常后不希望将异常继续向上层抛出,也可以通过 TransactionAspectSupport 类手动标记事务为回滚状态。

import org.springframework.transaction.interceptor.TransactionAspectSupport;

@Transactional
public void transactionalMethod() {
    try {
        // 业务逻辑
    } catch (Exception e) {
        // 处理异常
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); // 手动标记回滚
    }
}

这样,在捕获并处理异常后,事务管理器就能正确地检测到异常并触发事务回滚。

3、自调用问题

如果一个事务方法自己直接或间接地调用了自己,事务可能会失效。

解决方案

避免方法自调用,可以将自调用的部分提取到一个新的方法中,并通过方法调用来实现逻辑。

4、多线程问题

如果一个事务方法内部启动了多个线程,而这些线程没有正确地传播事务上下文,事务可能会失效。

解决方案

在多线程环境下,确保事务上下文能够正确传播到新线程中。可以通过使用 TransactionTemplate 来确保事务上下文正确传播。

5、事务传播行为不匹配

如果事务方法之间的传播行为设置不正确,如一个方法设置为 REQUIRED 而另一个设置为 REQUIRES_NEW,事务可能会失效。

解决方案

确保事务方法之间的传播行为设置正确。一般来说,如果方法内部调用了其他方法,应该保持传播行为一致,以避免事务失效的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你小子在看什么……

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值