java中Spring事务失效的8个常见案例和解决方案

 更新时间:2025年06月07日 10:11:16   投稿:yin  
本文分析了8种Spring事务失效问题及解决方案,涵盖注解应用、方法调用、异常处理、数据库支持、传播行为、类管理与事务管理器配置等,强调正确配置对数据一致性的重要性

Spring事务管理是企业级Java应用的核心功能,如果使用不当将会引发严重的生产问题,比如因事务失效带来的数据不一致问题。事务失效往往不会抛出异常,而是静默发生,等到业务出现问题时才被发现,造成严重的数据不一致。本文将分析8种导致Spring事务失效的使用问题并提供相应的解决方案。

一、事务注解应用在非public方法上

问题现象

开发者在非public方法上添加@Transactional注解,但事务没有生效。

Spring事务失效的8个经典大坑_事务管理

Spring AOP的代理机制默认只拦截public方法。

这是因为事务通知是基于Spring AOP实现的,而Spring AOP默认只拦截public方法调用。

查看AbstractFallbackTransactionAttributeSource类的源码可以发现:

// AbstractFallbackTransactionAttributeSource.java
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
    // Don't allow no-public methods as required.
    if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
        return null;
    }
    // ...
}

非public方法上的@Transactional注解会被直接忽略,返回null,导致事务不生效。

解决方案

确保标注@Transactional的方法为public:

Spring事务失效的8个经典大坑_事务管理_02

二、同一个类中方法调用

问题现象

在同一个类中,非事务方法调用事务方法,或者事务方法调用另一个具有不同事务属性的方法,事务会失效。

Spring事务失效的8个经典大坑_事务管理_03

原理分析

Spring事务失效的8个经典大坑_事务管理_04

解决方案

有几种方法可以解决:

方法1:使用自我注入

Spring事务失效的8个经典大坑_事务管理_05

方法2:使用AopContext获取代理对象(需要额外配置)

Spring事务失效的8个经典大坑_事务管理_06

方法3:将方法拆分到不同的类中

Spring事务失效的8个经典大坑_解决方案_07

三、异常被吞没

问题现象

开发者在事务方法中捕获了异常但没有重新抛出,导致事务无法回滚。

Spring事务失效的8个经典大坑_回滚_08

原理分析

Spring事务失效的8个经典大坑_事务管理_09

解决方案

有两种解决方法:

方法1:重新抛出异常

Spring事务失效的8个经典大坑_事务管理_10

方法2:使用TransactionAspectSupport手动回滚

Spring事务失效的8个经典大坑_回滚_11

四、异常类型不匹配回滚规则

问题现象

开发者抛出了异常,但事务没有回滚。

这通常是因为抛出的异常类型不满足默认的回滚规则。

Spring事务失效的8个经典大坑_回滚_12

原理分析

Spring默认只在遇到未检查异常(RuntimeException及其子类)和Error时才回滚事务。

受检异常(如IOException、SQLException)被认为是业务异常,默认情况下不会触发事务回滚。

这是因为@Transactional注解的默认配置是:

@Transactional(rollbackFor = RuntimeException.class)

解决方案

有两种解决方法:

方法1:指定回滚的异常类型

Spring事务失效的8个经典大坑_解决方案_13

方法2:将受检异常转换为非受检异常

Spring事务失效的8个经典大坑_回滚_14

五、数据库不支持事务

问题现象

所有事务配置看起来都正确,但事务仍然不生效。

原理分析

Spring事务失效的8个经典大坑_回滚_15

解决方案

确保使用支持事务的数据库引擎:

  1. 1. 对于MySQL,使用InnoDB引擎而不是MyISAM
  2. 2. 检查表的创建语句,确保引擎类型正确:
-- 检查表引擎
SHOW TABLE STATUS WHERE Name = 'your_table_name';

-- 修改表引擎为InnoDB
ALTER TABLE your_table_name ENGINE=InnoDB;

六、错误的传播行为设置

问题现象

在嵌套事务场景中,内部事务的回滚没有按照预期工作。

Spring事务失效的8个经典大坑_回滚_16

原理分析

Spring提供了不同的事务传播行为,用于控制事务的边界。

最常用的是:

Spring事务失效的8个经典大坑_事务管理_17

使用不当的传播行为会导致事务范围不符合预期,特别是在异常处理场景中。

解决方案

根据业务需求选择正确的传播行为:

Spring事务失效的8个经典大坑_事务管理_18

传播行为选择指南

Spring事务失效的8个经典大坑_回滚_19

七、未被Spring管理的类

问题现象

在类上添加了@Transactional注解,但事务没有生效。

Spring事务失效的8个经典大坑_回滚_20

原理分析

Spring事务失效的8个经典大坑_事务管理_21

解决方案

确保类被Spring容器管理:

@Service // 正确:添加@Service注解
public class UserService {
    
    @Autowired
    private UserMapper userMapper;
    
    @Transactional
    public void createUser(User user) {
        userMapper.insert(user);
        throw new RuntimeException("测试");
        // 现在事务会正常回滚
    }
}

同时,确保组件扫描配置正确:

@Configuration
@ComponentScan("com.example.service") // 确保包路径正确
public class AppConfig {
    // ...
}

八、事务管理器配置错误

问题现象

使用了正确的事务注解,但事务不生效或者出现异常。

原理分析

Spring支持多种事务管理器,针对不同的持久化技术:

Spring事务失效的8个经典大坑_回滚_22

如果配置了错误的事务管理器,或者在多数据源环境中未指定正确的事务管理器,会导致事务失效。

解决方案

单数据源环境:确保配置正确的事务管理器

Spring事务失效的8个经典大坑_回滚_23

多数据源环境:指定使用的事务管理器

@Configuration
@EnableTransactionManagement
public class MultiDatabaseConfig {
    
    @Bean
    public DataSource primaryDataSource() {
        // 主数据源配置...
        return new HikariDataSource();
    }
    
    @Bean
    public DataSource secondaryDataSource() {
        // 次数据源配置...
        return new HikariDataSource();
    }
    
    @Bean
    public PlatformTransactionManager primaryTransactionManager() {
        return new DataSourceTransactionManager(primaryDataSource());
    }
    
    @Bean
    public PlatformTransactionManager secondaryTransactionManager() {
        return new DataSourceTransactionManager(secondaryDataSource());
    }
}

@Service
public class UserService {
    
    // 指定使用的事务管理器
    @Transactional(transactionManager = "primaryTransactionManager")
    public void createUser(User user) {
        // 使用主数据源的操作
    }
    
    @Transactional(transactionManager = "secondaryTransactionManager")
    public void createUserLog(UserLog log) {
        // 使用次数据源的操作
    }
}

总结

到此这篇关于java中Spring事务失效的8个常见案例和解决方案的文章就介绍到这了,更多相关Spring事务失效的8个常见案例内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot如何自定义pom内子依赖版本

    springboot如何自定义pom内子依赖版本

    这篇文章主要介绍了springboot如何自定义pom内子依赖版本问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-08-08
  • 使用Swagger时Controller中api接口显示不全的问题分析及解决

    使用Swagger时Controller中api接口显示不全的问题分析及解决

    swagger是一个十分好用的api接口管理、测试框架,现在越来越多的人使用这个做接口的测试和管理,但经常遇到Controller中的api接口显示不全的问题,所以本文给大家详细分析了问题以及解决方法,需要的朋友可以参考下
    2024-02-02
  • Springboot整合Urule的方法步骤

    Springboot整合Urule的方法步骤

    这篇文章主要介绍了Springboot整合Urule的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-05-05
  • Spring Bean的初始化过程流程解析

    Spring Bean的初始化过程流程解析

    这篇文章主要介绍了Spring Bean的初始化过程是怎么样的,本文将以面试官的视角,全面解析 Bean 初始化流程,附带典型面试题与实战讲解,帮助你在技术面试中脱颖而出,需要的朋友可以参考下
    2025-06-06
  • springsecurity实现用户登录认证快速使用示例代码(前后端分离项目)

    springsecurity实现用户登录认证快速使用示例代码(前后端分离项目)

    这篇文章主要介绍了springsecurity实现用户登录认证快速使用示例代码(前后端分离项目),本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2024-03-03
  • apollo与springboot集成实现动态刷新配置的教程详解

    apollo与springboot集成实现动态刷新配置的教程详解

    这篇文章主要介绍了apollo与springboot集成实现动态刷新配置,本文分步骤给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • mybatis plus实现分页逻辑删除

    mybatis plus实现分页逻辑删除

    这篇文章主要为大家介绍了mybatis plus实现分页逻辑删除的方式详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • 基于HttpClient在HTTP协议接口测试中的使用(详解)

    基于HttpClient在HTTP协议接口测试中的使用(详解)

    下面小编就为大家带来一篇基于HttpClient在HTTP协议接口测试中的使用(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-10-10
  • JAVA使用ElasticSearch查询in和not in的实现方式

    JAVA使用ElasticSearch查询in和not in的实现方式

    今天小编就为大家分享一篇关于JAVA使用Elasticsearch查询in和not in的实现方式,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2018-12-12
  • java读写excel文件实现POI解析Excel的方法

    java读写excel文件实现POI解析Excel的方法

    在日常工作中,我们常常会进行Excel文件读写操作,这篇文章主要介绍了java读写excel文件实现POI解析Excel的方法,实例分析了java读写excel的技巧,非常具有实用价值,需要的朋友可以参考下
    2018-10-10

最新评论