You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot集成MyBatis事务无法回滚问题求助

问题分析与解决方案

从你的描述来看,核心问题是Spring的@Transactional注解在Wildfly 9容器里没正确触发回滚——哪怕抛出了RuntimeException或者手动设置了回滚标记,数据还是被提交了。结合你的技术栈(Spring Boot 2.1.8 + Wildfly 9 + MyBatis),我梳理了几个最可能的原因和对应的解决步骤:

1. 容器接管数据源导致Spring事务管理器失效

Wildfly作为Java EE容器,会自动识别并管理数据源,很可能覆盖了你在application.properties里配置的Spring Boot数据源。这时候Spring默认的DataSourceTransactionManager(本地事务管理器)根本控制不了容器管理的数据源,事务实际由Wildfly的JTA事务管理器接管,但Spring的@Transactional注解没和容器的事务系统正确绑定,自然不会触发回滚。

解决方法:

有两种思路可选:

  • 适配容器的JTA事务:在Spring Boot里配置JtaTransactionManager,让Spring事务和Wildfly的JTA机制对接。新增一个配置类:
@Configuration
public class TransactionConfig {
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new JtaTransactionManager();
    }
}
  • 禁止容器接管数据源:在项目的WEB-INF目录下创建jboss-deployment-structure.xml,阻止Wildfly干预你的数据源配置:
<jboss-deployment-structure>
    <deployment>
        <exclude-subsystems>
            <subsystem name="datasources"/>
        </exclude-subsystems>
    </deployment>
</jboss-deployment-structure>

这样Spring Boot就能完全掌控自己配置的数据源,用本地事务管理器处理事务。

2. 检查@EnableTransactionManagement的代理模式

默认情况下,@EnableTransactionManagement用JDK动态代理,只对接口生效。你的MyService是普通类而非接口,虽然Spring Boot默认会 fallback 到CGLIB代理,但如果项目里有其他框架的代理(比如AOP相关),可能会导致事务切面没正确织入。

解决方法:

修改@EnableTransactionManagement注解,强制使用CGLIB代理:

@SpringBootApplication
@EnableTransactionManagement(proxyTargetClass = true)
@ComponentScan("my.package")
public class ServletInitializer extends SpringBootServletInitializer {
    // 原有代码保持不变
}

3. 开启事务调试日志排查细节

要搞清楚事务到底有没有被创建、有没有触发回滚,最直接的方式是开Spring事务的DEBUG日志。在你的日志配置(比如logback.xml或log4j.properties)里加这段配置:

<!-- Logback示例配置 -->
<logger name="org.springframework.transaction" level="DEBUG"/>
<logger name="org.springframework.jdbc.datasource.DataSourceTransactionManager" level="DEBUG"/>

跑测试之后看日志:如果看不到Creating new transaction with name [my.package.MyService.doTask]或者Initiating transaction rollback这类日志,说明事务切面根本没生效;如果有回滚日志但数据还是提交了,那基本可以确定是数据源被容器接管的问题。

4. 确认MyBatis与Spring事务的绑定

虽然你用了mybatis-spring-boot-starter,自动配置应该能把MyBatis和Spring事务绑定,但还是可以额外检查两点:

  • 确保你的MyMapper接口加了@Mapper注解,或者在mybatis-config.xml里正确配置了mapper扫描路径;
  • 可以显式声明SqlSessionFactory,确保它用的是Spring管理的数据源:
@Configuration
public class MyBatisConfig {
    @Autowired
    private DataSource dataSource;

    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setConfigLocation(new ClassPathResource("mybatis-config.xml"));
        return sessionFactory.getObject();
    }
}

5. 显式指定事务传播行为

虽然默认的Propagation.REQUIRED传播行为是没问题的,但可以尝试显式指定,确保事务被正确创建:

@Transactional(rollbackFor = Throwable.class, propagation = Propagation.REQUIRED)
public void doTask() {
    // 原有业务代码不变
}

按照上面的步骤逐一排查,应该能解决事务不回滚的问题。

内容的提问来源于stack exchange,提问作者Raj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:50:45