我无法让事务在我的基本 spring data mongodb 应用程序中工作。我在这里读过文章和类似的问题,但似乎没有任何帮助。该测试正在使用 Testcontainers 运行,它似乎使用副本集启动 Mongo,这意味着事务应该正常工作。我确信测试配置至少可以在非事务性代码中正常工作(更多内容请参见最后的 github 链接)。
域名服务:
public class EntityDomainService {
private final EntityARepository repository;
private final EntityBRepository entityBRepository;
EntityDomainService(EntityARepository repository, EntityBRepository entityBRepository) {
this.repository = repository;
this.entityBRepository = entityBRepository;
}
@Transactional
public void transactionalAdd(String id1, String id2) {
repository.save(EntityA.builder().id(id1).build());
fail();
repository.save(EntityA.builder().id(id2).build());
}
private void fail() {
throw new RuntimeException();
}
}
模块特定配置:
@Configuration
@EnableMongoRepositories
class EntityDomainConfiguration {
@Bean
EntityDomainService domainService(
EntityARepository entityARepository, EntityBRepository entityBRepository) {
return new EntityDomainService(entityARepository, entityBRepository);
}
}
“全局”Mongo 配置:
@Configuration
@EnableMongoRepositories()
@EnableTransactionManagement
class ApplicationConfiguration extends AbstractMongoClientConfiguration {
// usual stuff
@Bean
MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
return new MongoTransactionManager(dbFactory);
}
}
测试 Mongo 容器配置:
@EnableMongoRepositories
public class MongoDBContainerTestConfiguration {
@Bean
@ServiceConnection
public MongoDBContainer mongoDBContainer() {
return new MongoDBContainer(DockerImageName.parse("mongo:7.0")).withExposedPorts(27017);
}
}
最后,测试本身:
@Testcontainers
@DataMongoTest
@ContextConfiguration(classes = [MongoDBContainerTestConfiguration.class])
class EntityADomainSpec extends Specification {
@Autowired EntityAMongoRepository simulationRepository
@Autowired EntityBMongoRepository plotRepository
EntityDomainService service
def setup() {
service = new EntityDomainConfiguration().domainService(simulationRepository, plotRepository)
}
def cleanup() {
simulationRepository.deleteAll()
plotRepository.deleteAll()
}
def "basic transaction test"() {
when:
service.transactionalAdd("abc", "def")
then:
thrown(RuntimeException)
!simulationRepository.existsById("abc")
}
}
整个最小的可重现示例托管在我的 github 上(我希望它被修剪到最少,但这是我的第一次尝试)。它包含一项通过测试(以显示配置的有效性)和事务行为的实际测试: https://github.com/rafalszulejko/mongotransactions
编辑:从 github 托管的示例中删除了很多代码
答案是将非测试配置添加到
@ContextConfiguration
。
@ContextConfiguration(classes = [EntityDomainConfiguration.class, MongoDBContainerTestConfiguration.class])