我创建了一个应用程序,该应用程序基于此tutorial将数据从一个数据库复制到另一个数据库。 实际上,我需要创建一种在事务中插入两个不同数据库的方法。 MongoDB有可能吗?以及如何实施?
答案 0 :(得分:0)
要在Spring Data MongoDB中的多个数据库中使用MongoDB中的多文档事务,您需要为每个数据库配置MongoTemplate
,但是它们都必须使用相同的MongoDbFactory
,因为它被视为交易资源。
这意味着您将需要重写MongoTemplate
的几种方法以使其使用应使用的数据库(而不是SimpleMongoClientDbFactory
内部配置的数据库)。
让我们假设您的数据库被称为“一个”和“两个”。然后是这样的:
public class MongoTemplateWithFixedDatabase extends MongoTemplate {
private final MongoDbFactory mongoDbFactory;
private final String databaseName;
public MongoTemplateWithFixedDatabase(MongoDbFactory mongoDbFactory,
MappingMongoConverter mappingMongoConverter, String databaseName) {
super(mongoDbFactory, mappingMongoConverter);
this.mongoDbFactory = mongoDbFactory;
this.databaseName = databaseName;
}
@Override
protected MongoDatabase doGetDatabase() {
return MongoDatabaseUtils.getDatabase(databaseName, mongoDbFactory, ON_ACTUAL_TRANSACTION);
}
}
和
@Bean
public MongoDbFactory mongoDbFactory() {
// here, some 'default' database name is configured, the following MongoTemplate instances will ignore it
return new SimpleMongoDbFactory(mongoClient(), getDatabaseName());
}
@Bean
public MongoTransactionManager mongoTransactionManager() {
return new MongoTransactionManager(mongoDbFactory());
}
@Bean
public MongoTemplate mongoTemplateOne(MongoDbFactory mongoDbFactory,
MappingMongoConverter mappingMongoConverter) {
MongoTemplate template = new MongoTemplateWithFixedDatabase(mongoDbFactory,
mappingMongoConverter, "one");
return template;
}
@Bean
public MongoTemplate mongoTemplateTwo(MongoDbFactory mongoDbFactory,
MappingMongoConverter mappingMongoConverter) {
MongoTemplate template = new MongoTemplateWithFixedDatabase(mongoDbFactory,
mappingMongoConverter, "two");
return template;
}
然后只需在服务中注入mongoTemplateOne
和mongoTemplateTwo
,并用@Transactional
标记其方法即可。
在反应性情况下,它非常相似。当然,您需要使用诸如ReactiveMongoTemplate
,ReactiveMongoDatabaseFactory
,ReactiveMongoTransactionManager
之类的反应式版本。
还有一些警告。首先,您必须重写3种方法,而不是2种(因为getCollection(String)
也需要重写)。另外,我必须使用抽象类来使其起作用:
@Bean
public ReactiveMongoOperations reactiveMongoTemplateOne(
@ReactiveMongoDatabaseFactory reactiveMongoDatabaseFactory,
MappingMongoConverter mappingMongoConverter) {
ReactiveMongoTemplate template = new ReactiveMongoTemplate(reactiveMongoDatabaseFactory,
mappingMongoConverter) {
@Override
protected Mono<MongoDatabase> doGetDatabase() {
return ReactiveMongoDatabaseUtils.getDatabase("one", reactiveMongoDatabaseFactory,
ON_ACTUAL_TRANSACTION);
}
@Override
public MongoDatabase getMongoDatabase() {
return reactiveMongoDatabaseFactory.getMongoDatabase(getDatabaseName());
}
@Override
public MongoCollection<Document> getCollection(String collectionName) {
Assert.notNull(collectionName, "Collection name must not be null!");
try {
return reactiveMongoDatabaseFactory.getMongoDatabase(getDatabaseName())
.getCollection(collectionName);
} catch (RuntimeException e) {
throw potentiallyConvertRuntimeException(e,
reactiveMongoDatabaseFactory.getExceptionTranslator());
}
}
private RuntimeException potentiallyConvertRuntimeException(RuntimeException ex,
PersistenceExceptionTranslator exceptionTranslator) {
RuntimeException resolved = exceptionTranslator.translateExceptionIfPossible(ex);
return resolved == null ? ex : resolved;
}
};
return template;
}
P.S。所提供的代码已在spring-data-mongodb 2.2.4中进行了测试。