“什么情况下@Transaction注解的事务会失效”的版本间的差异

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

2024年7月16日 (二) 02:00的最新版本

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

@Transaction注解的事务代码示例

模拟@Transaction注解的事务失效

注解事务失效的解决方案