过去一周我一直在努力将Spring Data MongoDB成功集成到我们的应用程序中。我们使用相当普遍的做法,为我们依赖的每个集合提供单独的数据库。例如,TenantConfiguration数据库仅包含TenantConfigurations集合。
我已多次阅读文档,并通过代码搜索解决方案,但一无所获。当然这样一个广泛采用的项目对这个问题有一些解决方案吗?我目前的尝试看起来像这样:
QPair<double, bool> toDouble(QString in) {
auto dots = in.count('.');
auto commas = in.count(',');
if ((dots > 1 && commas > 1) || (dots == 1 && commas ==1))
// equivocal input
return qMakePair(0.0, false);
if (dots > 1 && commas <=1) {
// dots are group separators
in.replace(".", "");
in.replace(',', '.');
}
else if (dots <= 1 && commas > 1) {
// commas are group separators
in.replace(",", "");
}
else if (commas == 1) {
// assume commas are decimal points
in.replace(',', '.');
}
bool ok;
auto dbl = in.toDouble(&ok);
return qMakePair(dbl, ok);
}
以下是其他单个存储库配置之一:
@Configuration
@EnableMongoRepositories(basePackages = "com.whatever.service.repository",
basePackageClasses = TenantConfigurationRepository.class,
mongoTemplateRef = "tenantConfigurationTemplate")
public class TenantConfigurationRepositoryConfig {
@Value("${mongo.hosts}")
private List<String> mongoHosts;
@Bean
public MongoTemplate tenantConfigurationTemplate() throws Exception {
final List<ServerAddress> serverAddresses = new ArrayList<>();
for (String host : mongoHosts) {
serverAddresses.add(new ServerAddress(host, 27017));
}
final MongoClientOptions clientOptions = new MongoClientOptions.Builder()
.connectTimeout(25000)
.readPreference(ReadPreference.primaryPreferred())
.build();
final MongoClient client = new MongoClient(serverAddresses, clientOptions);
return new MongoTemplate(client, "TenantConfiguration");
}
}
现在这里是RegisteredCard存储库的实际存储库定义:
@Configuration
@EnableMongoRepositories(basePackages = "com.whatever.service.repository",
basePackageClasses = RegisteredCardRepository.class,
mongoTemplateRef = "registeredCardTemplate")
public class RegisteredCardRepositoryConfig {
@Value("${mongo.hosts}")
private List<String> mongoHosts;
@Bean
public MongoTemplate registeredCardTemplate() throws Exception {
final List<ServerAddress> serverAddresses = new ArrayList<>();
for (String host : mongoHosts) {
serverAddresses.add(new ServerAddress(host, 27017));
}
final MongoClientOptions clientOptions = new MongoClientOptions.Builder()
.connectTimeout(25000)
.readPreference(ReadPreference.primaryPreferred())
.build();
final MongoClient client = new MongoClient(serverAddresses, clientOptions);
return new MongoTemplate(client, "RegisteredCard");
}
}
这对我来说非常有意义,各个配置唯一地标识它们配置的特定存储库接口以及特定模板bean,以通过{{{ 1}}注释的参数。至少,这就是文档似乎意味着它应该起作用的方式。
实际上,当我启动应用程序时,RegisteredCard存储库解析为MongoDB存储库实例,该实例具有绑定到TenantConfiguration数据库的关联@Repository
public interface RegisteredCardRepository extends MongoRepository<RegisteredCard, Guid>,
QueryDslPredicateExecutor<RegisteredCard> { }
。实际上,每个存储库都会收到相同的,不正确的MongoOperations对象。尽管每个存储库都有自己独特的配置,但似乎首先访问的数据库仍然是每个存储库的目标数据库。
这个问题有什么解决方案吗?
答案 0 :(得分:3)
这花了我差不多一个星期,但实际上我找到了一个可以解决这个问题的方法。这是我在研究这个问题时所掌握的事实的快速消解:
@EnableMongoRepositories(basePackageClasses = Whatever.class)
只是使用限定类名来指示它应扫描所有所定义数据模型的包。如果@EnableMongoRepositories(basePackageClasses = "com.mypackage.whatevers")
驻留在该包中,这完全等同于执行Whatever.class
。 @EnableMongoRepositories
不可重复,但可用于注释多个类。其他SO对话已经涵盖了这一点,但在此重复。您需要定义几个存储库配置类; 您打算与之互动的每个数据库一个。MongoTemplate
注释中指定自己的@EnableMongoRepositories
实例。您只能提供一个Mongo
bean,但MongoTemplate
依赖于特定的MongoMappingContext
。 @EnableMongoRepositories
注释有助于定义映射上下文,这可以理解数据模型的结构以及如何序列化它们。它还了解@Document
和@Field
注释,并且可以解决持久存在的问题。 Mongo模板实例是您指定要与之交互的数据库的位置。因此,通过提供@EnableMongoRepositories
注释以及basePackage
属性和mongoTemplateRef
属性,您可以告诉Spring Data Mongo“获取这些模型并将其保留在此特定数据库中”。 此解决方案的不幸要求是您必须根据数据库所属的数据库将数据模型组织到单独的包中。如果像我一样,您使用的Mongo数据库结构将单个集合分配给每个数据库(这对于访问量很大的集合来说,这是很常见的),这意味着每个数据模型都必须位于自己的包中。每个包都必须由@EnableMongoRepositories
注释指向,该注释还包含mongoTemplateRef
个唯一MongoTemplate
bean的属性。
我希望这可以帮助别人避免我试图完成应该是一个相当普通的Mongo集成的麻烦。
PS:放弃所有希望,那些寻求将审计与此配置相结合的人。