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
相关产品推荐
相关产品推荐

