【问题标题】:Can Spring Data MongoDB be configured to support a different database for each repository?Spring Data MongoDB 可以配置为每个存储库支持不同的数据库吗?
【发布时间】:2016-10-31 08:59:30
【问题描述】:

过去一周我一直在努力将 Spring Data MongoDB 成功集成到我们的应用程序中。我们使用相当普遍的做法,即为我们所依赖的每个集合设置单独的数据库。例如,TenantConfiguration 数据库仅包含 TenantConfigurations 集合。

我已多次阅读文档并浏览代码以寻求解决方案,但一无所获。这样一个被广泛采用的项目肯定有解决这个问题的办法吗?我目前的尝试是这样的:

@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");
    }
}

这是其他单独的存储库配置之一:

@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");
    }
}

现在这里是 RegisteredCard 存储库的实际存储库定义:

@Repository
public interface RegisteredCardRepository extends MongoRepository<RegisteredCard, Guid>,
        QueryDslPredicateExecutor<RegisteredCard> { }

这一切对我来说都很有意义,各个配置唯一地标识了他们配置的特定存储库接口以及通过@987654324与该存储库一起使用的特定模板bean @注解的参数。至少,文档似乎暗示它应该是这样工作的。

实际上,当我启动应用程序时,RegisteredCard 存储库解析为一个 MongoDB 存储库实例,该实例具有关联的 MongoDbFactory,该实例绑定到 TenantConfiguration 数据库。事实上,每个存储库都会收到相同的、不正确的 MongoOperations 对象。尽管每个存储库都有自己独特的配置,但似乎首先访问的任何数据库仍然是 每个 存储库的目标数据库。

是否有任何解决方案可以解决这个问题?

【问题讨论】:

    标签: spring mongodb spring-data spring-data-mongodb


    【解决方案1】:

    我花了将近一周的时间,但实际上我已经找到了解决此问题的可行解决方案。以下是我在研究此问题时收集到的事实的简要说明:

    • @EnableMongoRepositories(basePackageClasses = Whatever.class) 简单地使用一个合格的类名来指示它应该扫描什么 以查找您定义的数据模型的所有。如果Whatever.class 驻留在该包中,这完全等同于执行@EnableMongoRepositories(basePackageClasses = "com.mypackage.whatevers")
    • @EnableMongoRepositories 不可重复,但可用于注释多个类。这已在其他 SO 对话中介绍过,但在这里需要重复。您将需要定义 几个 存储库配置类; 您打算与之交互的每个数据库都有一个
    • 每个单独的存储库配置都必须在 @EnableMongoRepositories 注释中指定自己的 MongoTemplate 实例。您可以只提供一个Mongo bean,但MongoTemplate 依赖于特定的MongoMappingContext
    • @EnableMongoRepositories 注释有助于定义映射上下文,它了解数据模型的结构以及如何序列化它们。它还理解@Document@Field 注释,并完成持久化对象的繁重工作。 Mongo 模板实例是您指定要与之交互的数据库的地方。因此,通过为@EnableMongoRepositories 注释提供basePackage 属性和mongoTemplateRef 属性,您可以告诉Spring Data Mongo“获取这些模型并将它们持久保存在这个特定的数据库中”。

    这个解决方案的不幸要求是,您必须根据数据模型所属的数据库将数据模型组织到单独的包中。如果像我一样,您使用的是 Mongo 数据库结构,它为每个数据库分配一个集合(这对于频繁访问的集合来说是相当常见的),这意味着您的每个数据模型都必须驻留在自己的包中。这些包中的每一个都必须由一个 @EnableMongoRepositories 注释指向,该注释还包含一个唯一 MongoTemplate bean 的 mongoTemplateRef 属性。

    我希望这可以帮助某人避免我在尝试完成应该是相当普通的 Mongo 集成时遇到的麻烦。

    PS:放弃所有希望,那些寻求将审计与此配置相结合的人。

    【讨论】:

      【解决方案2】:

      我知道这已经过时了,但对于像我这样正在寻找简短解决方案的人来说:

      @Autowired
      @Qualifier("registeredCardTemplate")
      private MongoTemplate template;
      

      限定符名称是您的“mongoTemplateRef={XXX}”

      【讨论】:

        猜你喜欢
        • 2015-10-19
        • 1970-01-01
        • 1970-01-01
        • 2012-05-06
        • 1970-01-01
        • 2014-11-04
        • 2020-02-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多