• 使用 Spring Data MongoDB 连接到多个数据库


    1. 概述

    使用 Spring Data MongoDB,我们可以创建一个MongoClient来对数据库进行操作。但是,有时,我们可能需要在应用程序中使用多个数据库。

    在本教程中,我们将创建到 MongoDB 的多个连接。我们还将添加一些 Spring Boot 测试来模拟这个场景。

    2. Spring Data MongoDB 的多数据库应用

    使用MongoDB时,我们创建一个MongoTemplate来访问数据。因此,我们可以创建多个模板来连接各种数据库。

    但是,我们可以得到NoUniqueBeanDefinitionException,因为 Spring 没有找到唯一的 bean。

    考虑到这一点,让我们看看如何构建 Spring Boot 配置。

    2.1. 依赖设置

    让我们从向pom.xml 添加依赖项开始。首先,我们需要一个spring boot 启动器

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.6.4version>
        <relativePath />
    parent>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后,我们需要一个web starter数据 MongoDB的依赖项:

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-data-mongodbartifactId>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    同样,如果我们使用 Gradle,我们添加到build.gradle

    plugins {
        id 'org.springframework.boot' version '2.6.4'
    }
    compile 'org.springframework.boot:spring-boot-starter-data-mongodb'
    compile 'org.springframework.boot:spring-boot-starter-web'
    
    • 1
    • 2
    • 3
    • 4
    • 5

    作为替代方案,我们可以使用Spring Initializer

    2.2. 模型(Model)

    首先,让我们添加我们的模型。我们将创建两个文档,供两个不同的数据库使用。

    例如,我们将创建一个 User 文档:

    @Document(collection = "user")
    public class User {
    
        @MongoId
        private ObjectId id;
    
        private String name;
    
        private String surname;
        private String email;
    
        private int age;
    
        // getters and setters
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    然后,我们还要添加一个 Account 文档:

    @Document(collection = "account")
    public class Account {
    
        @MongoId
        private ObjectId id;
    
        private String userEmail;
    
        private String nickName;
    
        private String accountDomain;
    
        private String password;
    
        // getters and setters
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.3. 存储库(Repository)

    然后,我们使用一些 Spring Data 方法为每个模型类创建一个存储库。

    首先,让我们添加一个UserRepository

    @Repository
    public interface UserRepository extends MongoRepository<User, String> {
    
        User findByEmail(String email);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    接下来,我们添加一个AccountRepository

    @Repository
    public interface AccountRepository extends MongoRepository<Account, String> {
    
        Account findByAccountDomain(String account);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2.4. 连接属性

    让我们定义我们正在使用的多个数据库的属性:

    mongodb.primary.host=localhost
    mongodb.primary.database=db1
    mongodb.primary.authenticationDatabase=admin
    mongodb.primary.username=user1
    mongodb.primary.password=password
    mongodb.primary.port=27017
    
    mongodb.secondary.host=localhost
    mongodb.secondary.database=db2
    mongodb.secondary.authenticationDatabase=admin
    mongodb.secondary.username=user2
    mongodb.secondary.password=password
    mongodb.secondary.port=27017
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    值得注意的是,我们有一个用于身份验证的特定数据库的属性。

    2.5. Primary 配置

    现在,我们需要我们的配置。我们将为每个数据库制作一个。

    让我们看一下用于UserRepository的Primary 类定义:

    @Configuration
    @EnableMongoRepositories(basePackageClasses = UserRepository.class, mongoTemplateRef = "primaryMongoTemplate")
    @EnableConfigurationProperties
    public class PrimaryConfig {
        // beans
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    为了演示,让我们分解所有的 bean 和注释。

    首先,我们将使用*MongoProperties检索和设置属性。*这样,我们直接将所有属性映射到一个 bean:

    @Bean(name = "primaryProperties")
    @ConfigurationProperties(prefix = "mongodb.primary")
    @Primary
    public MongoProperties primaryProperties() {
        return new MongoProperties();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    为了向多个用户授予访问权限,我们使用 带有*MongoCredential的 MongoDB身份验证机制我们通过添加一个身份验证数据库来构造我们的凭证对象,在本例中为admin :*

    @Bean(name = "primaryMongoClient")
    public MongoClient mongoClient(@Qualifier("primaryProperties") MongoProperties mongoProperties) {
    
        MongoCredential credential = MongoCredential
          .createCredential(mongoProperties.getUsername(), mongoProperties.getAuthenticationDatabase(), mongoProperties.getPassword());
    
        return MongoClients.create(MongoClientSettings.builder()
          .applyToClusterSettings(builder -> builder
            .hosts(singletonList(new ServerAddress(mongoProperties.getHost(), mongoProperties.getPort()))))
          .credential(credential)
          .build());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    正如最新版本所建议的,我们使用SimpleMongoClientDatabaseFactory 而不是从连接字符串创建MongoTemplate

    @Primary
    @Bean(name = "primaryMongoDBFactory")
    public MongoDatabaseFactory mongoDatabaseFactory(
      @Qualifier("primaryMongoClient") MongoClient mongoClient, 
      @Qualifier("primaryProperties") MongoProperties mongoProperties) {
        return new SimpleMongoClientDatabaseFactory(mongoClient, mongoProperties.getDatabase());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    我们需要我们的 bean 在这里是*@Primary*,因为我们将添加更多的数据库配置。否则,我们将落入我们之前讨论过的唯一性约束。

    当我们映射多个EntityManager时,我们对 JPA 执行相同的操作。同样,我们需要在*@EnableMongoRepositories*中引用Mongotemplate:

    @EnableMongoRepositories(basePackageClasses = UserRepository.class, mongoTemplateRef = "primaryMongoTemplate")
    
    • 1

    2.6. Secondary 配置

    最后,为了仔细检查,让我们看一下第二个数据库配置:

    @Configuration
    @EnableMongoRepositories(basePackageClasses = AccountRepository.class, mongoTemplateRef = "secondaryMongoTemplate")
    @EnableConfigurationProperties
    public class SecondaryConfig {
    
        @Bean(name = "secondaryProperties")
        @ConfigurationProperties(prefix = "mongodb.secondary")
        public MongoProperties secondaryProperties() {
            return new MongoProperties();
        }
    
        @Bean(name = "secondaryMongoClient")
        public MongoClient mongoClient(@Qualifier("secondaryProperties") MongoProperties mongoProperties) {
    
            MongoCredential credential = MongoCredential
              .createCredential(mongoProperties.getUsername(), mongoProperties.getAuthenticationDatabase(), mongoProperties.getPassword());
    
            return MongoClients.create(MongoClientSettings.builder()
              .applyToClusterSettings(builder -> builder
                .hosts(singletonList(new ServerAddress(mongoProperties.getHost(), mongodProperties.getPort()))))
              .credential(credential)
              .build());
        }
    
        @Bean(name = "secondaryMongoDBFactory")
        public MongoDatabaseFactory mongoDatabaseFactory(
          @Qualifier("secondaryMongoClient") MongoClient mongoClient, 
          @Qualifier("secondaryProperties") MongoProperties mongoProperties) {
            return new SimpleMongoClientDatabaseFactory(mongoClient, mongoProperties.getDatabase());
        }
    
        @Bean(name = "secondaryMongoTemplate")
        public MongoTemplate mongoTemplate(@Qualifier("secondaryMongoDBFactory") MongoDatabaseFactory mongoDatabaseFactory) {
            return new MongoTemplate(mongoDatabaseFactory);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    在这种情况下,它将引用AccountRepository或属于同一包的所有类*。*

    3. 测试

    我们将针对 MongoDB 实例测试应用程序。我们可以将MongoDB 与 Docker 一起使用。

    3.1. 启动一个 MongoDB 容器

    让我们使用Docker Compose运行一个 MongoDB 容器。让我们看看我们的 YAML 模板:

    services:
      mongo:
        hostname: localhost
        container_name: 'mongo'
        image: 'mongo:latest'
        expose:
          - 27017
        ports:
          - 27017:27017
        environment:
          - MONGO_INITDB_DATABASE=admin
          - MONGO_INITDB_ROOT_USERNAME=admin
          - MONGO_INITDB_ROOT_PASSWORD=admin
        volumes:
          - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    如果我们想要进行身份验证,我们需要使用 root 用户进行初始化。为了用更多用户填充数据库,我们将绑定挂载添加到 JavaScript 初始化文件:

    db.createUser(
        {
            user: "user1",
            pwd: "password",
            roles: [ { role: "readWrite", db: "db1" } ]
        }
    )
    
    db.createUser(
        {
            user: "user2",
            pwd: "password",
            roles: [ { role: "readWrite", db: "db2" } ]
        }
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    让我们运行我们的容器:

    docker-compose up -d
    
    • 1

    当容器启动时,它会为mongo-init.js文件创建一个卷并将其复制到容器的入口点。

    3.2. Spring Boot 测试

    让我们在一些基本的Spring Boot 测试中将它们包装在一起:

    @SpringBootTest(classes = { SpringBootMultipeDbApplication.class })
    @TestPropertySource("/multipledb/multidb.properties")
    public class MultipleDbUnitTest {
    
        // set up
    
        @Test
        void whenFindUserByEmail_thenNameOk() {
            assertEquals("name", userRepository.findByEmail("user@gmail.com")
              .getName());
        }
    
        @Test
        void whenFindAccountByDomain_thenNickNameOk() {
            assertEquals("nickname", accountRepository.findByAccountDomain("account@jira.baeldung.com")
              .getNickName());
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    首先,我们要为数据库建立连接并获得身份验证。如果我们不这样做,我们可能没有填充数据库或没有启动 MongoDb 实例。

    在这些情况下,我们可以查看数据库容器的日志,例如:

    docker logs 30725c8635d4
    
    • 1

    值得注意的是,初始 JavaScript 仅在容器第一次运行时执行。因此,如果我们需要使用不同的脚本运行,我们可能需要删除卷:

    docker-compose down -v
    
    • 1

    4. 结论

    在本文中,我们了解了如何使用 Spring Data MongoDB 创建多个连接。我们看到了如何添加凭据以进行身份验证。最重要的是,我们已经了解了如何创建配置,其中之一必须是主 bean。最后,我们使用 Docker 和 Spring Boot 测试针对正在运行的 MongoDB 实例添加了一些测试用例.


    <<<<<<<<<<<< [完] >>>>>>>>>>>>

  • 相关阅读:
    R语言学习笔记
    图文结合丨Prometheus+Grafana+GreatSQL性能监控系统搭建指南(上)
    java RMI 协议通过zookeeper的实现
    Web测试中如何简单定位Bug
    ActivityStackSupervisor、ActivityStack、ActivityDisplay、TaskRecord、ActivityRecord
    调用别人接口的常用方法htticlient、resultTemple
    分布式数据库Schema 变更 in F1 & TiDB
    开心消消乐游戏网页设计作品 学生dreamweaver作业静态HTML网页设计模板 游戏主题网页作业制作
    十倍增量的海外客户开发新方式来了!外贸企业可直接照做
    电线电缆知识全面总结
  • 原文地址:https://blog.csdn.net/wjw465150/article/details/127785940