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

Weld/JUnit5测试中MyBatis-CDI的Transactional(rollbackOnly=true)不回滚事务

JUnit5 + Jakarta EE下Weld容器事务回滚失效解决方案

核心修正步骤

1. 补全Weld事务测试依赖

升级到JUnit5后,原JUnit4的事务扩展不再生效,必须引入Weld专门的JUnit5事务支持包:

<dependency>
    <groupId>org.jboss.weld.junit5</groupId>
    <artifactId>weld-junit5-transaction</artifactId>
    <version>5.1.0.Final</version>
    <scope>test</scope>
</dependency>

2. 替换事务注解与测试类配置

  • 彻底弃用旧的javax.transaction.Transactional,改用Jakarta官方注解:jakarta.transaction.Transactional
  • 测试类使用Weld JUnit5扩展+事务注解组合,替代手动初始化WeldInitiator:
@ExtendWith(WeldJunit5Extension.class)
@Transactional(rollbackOn = Exception.class)
public class UserMapperTest {
    @Inject
    private UserMapper userMapper;
    
    @Test
    void testInsertRollback() {
        User user = new User();
        user.setEmail("test@example.com");
        userMapper.insert(user);
        // 无需手动处理,@Transactional会自动触发回滚
    }
}

3. 修正MyBatis与Jakarta事务的绑定

自定义SqlSessionFactory提供者中,必须使用Jakarta兼容的事务工厂,确保MyBatis会话绑定到容器事务:

@Produces
@ApplicationScoped
public SqlSessionFactory produceSqlSessionFactory() throws IOException {
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    // 加载原有配置
    Configuration baseConfig = builder.build(Resources.getResourceAsStream("mybatis-config.xml")).getConfiguration();
    // 替换为JTA事务工厂(适配Jakarta)
    TransactionFactory transactionFactory = new JtaTransactionFactory();
    Environment env = new Environment("test-env", transactionFactory, baseConfig.getDataSource());
    Configuration newConfig = new Configuration(env);
    // 复用原有Mapper配置
    newConfig.addMappers(baseConfig.getMapperRegistry().getMappers());
    return builder.build(newConfig);
}

4. 启用beans.xml中的事务拦截器

确保beans.xml显式注册Jakarta事务拦截器,让容器能识别并处理@Transactional注解:

<beans xmlns="https://jakarta.ee/xml/ns/jakartaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_3_0.xsd"
       version="3.0" bean-discovery-mode="all">
    <interceptors>
        <class>jakarta.transaction.TransactionalInterceptor</class>
    </interceptors>
</beans>

5. 手动回滚兜底方案

若自动回滚仍失效,可在测试方法中手动控制事务:

@Inject
private UserTransaction userTransaction;

@Test
void testInsertRollback() throws Exception {
    try {
        userTransaction.begin();
        User user = new User();
        user.setEmail("test@example.com");
        userMapper.insert(user);
        userTransaction.rollback();
    } catch (Exception e) {
        if (userTransaction.getStatus() == Status.STATUS_ACTIVE) {
            userTransaction.rollback();
        }
        throw e;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 11:12:43