什么情况下@Transaction注解的事务会失效
跳到导航
跳到搜索
- 异常被捕获后没有抛出:如果在
@Transactional
注解的方法中捕获了异常,并且没有再次抛出该异常,那么事务将不会回滚。 - 抛出非运行时异常且未指定回滚异常类型:默认情况下,
@Transactional
注解仅会回滚抛出的运行时异常(RuntimeException)。如果抛出的是非运行时异常,且没有通过rollbackFor
属性指定回滚该异常类型,事务将不会回滚。但如果指定了回滚异常类型为该非运行时异常或其父类异常,那么就可以回滚该类型的异常。 - 方法内部直接调用:在同一个类中,一个方法直接调用另一个被
@Transactional
注解的方法,事务将不会生效。原因是直接调用不会经过 Spring 的代理,解决方法是将当前类自己注入,然后通过注入的对象来调用被注解的方法。 - 新开启一个线程:如果在
@Transactional
注解的方法中开启了新线程,在新线程中执行的数据库操作不会在当前事务中,因为 Spring 是通过ThreadLocal
把数据库连接绑定到当前线程的,新线程获取到的连接与原线程不同。 - 注解到非
public
方法或final
修饰的方法上:@Transactional
注解只能应用于public
方法,否则 Spring 无法生成动态代理来实现事务增强。此外,被final
修饰的方法也无法通过代理增强事务功能。 - 数据库本身不支持:例如使用的 MySQL 数据库,必须设置数据库引擎为 InnoDB,否则事务将不生效。
- 事务传播属性设置错误:如果设置了不恰当的传播属性,如
propagation_not_supported
(以非事务的方式执行,如果当前有事务则把当前事务挂起),可能导致事务行为不符合预期。 - 类未被 Spring 管理:如果使用
@Transactional
注解的类没有被 Spring 框架管理,事务也不会生效。 - 多线程调用:在多线程环境中,如果没有正确处理事务传播,可能导致事务失效。例如在一个事务方法中启动新的线程执行数据库操作,新线程中的操作可能不在原始事务范围内。
- 错误的传播特性:例如将传播特性设置为不支持事务的类型。
- 自己吞了异常:在事务方法中捕获异常后,没有进行任何处理或没有向外抛出,导致 Spring 框架无法感知到异常,从而不会回滚事务。
- 手动抛了其他异常:如果手动抛出的异常不符合默认的回滚规则(运行时异常),且没有正确配置
rollbackFor
,事务也不会回滚。