SpringBoot 实现 MongoDB 多数据源配置

it2022-05-05  140

文章目录

一、需求背景二、实现步骤1. 添加依赖2. 修改配置文件3. 重建数据源配置类AbstractMongoConfigurePrimaryMongoConfigureSecondaryMongoConfigure 4. 创建实体类与接口UserUserRepository 5. 调用示例

一、需求背景

MongoDB 是一个基于分布式存储的数据库,具备开源、高性能等特点,是当前 NoSQL 数据库中比较热门的一种。

同 MySQL 一样,SpringBoot 对 MongoDB 单数据源已经实现了很好的集成,大部分情况下都可以满足用户的需求。

但本次我们的需求是在 SpringBoot 项目中实现 MongoDB 多数据源配置,这就需要我们在原生 API 的基础上做一些改造,详情请见下文分解。

二、实现步骤

1. 添加依赖

第一步,需要在 pom.xml 文件中添加如下依赖:

<!-- MongoDB --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency> <!-- 自定义配置依赖包 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>

2. 修改配置文件

第二步,在配置文件 application.properties 中添加多数据源的信息:

spring.data.mongodb.database=admin spring.data.mongodb.host=127.0.0.1 spring.data.mongodb.port=27017 spring.data.mongodb.authenticationDatabase=admin spring.data.mongodb.username=mongodb spring.data.mongodb.password=mongodb spring.data.mongodb.primary.database=primary_data spring.data.mongodb.primary.host=127.0.0.1 spring.data.mongodb.primary.port=27017 spring.data.mongodb.primary.authenticationDatabase=admin spring.data.mongodb.primary.username=mongodb spring.data.mongodb.primary.password=mongodb spring.data.mongodb.secondary.database=secondary_data spring.data.mongodb.secondary.host=127.0.0.1 spring.data.mongodb.secondary.port=27017 spring.data.mongodb.secondary.authenticationDatabase=admin spring.data.mongodb.secondary.username=mongodb spring.data.mongodb.secondary.password=mongodb

需要注意的是,除了新增的 primary 与 secondary 数据源,原生的数据源也需进行正确配置。因为 SpringBoot 启动时会默认连接原生数据源,若没有正确配置,程序会抛出连接异常。当然,这个异常不会对程序其他部分造成影响。

3. 重建数据源配置类

第三步,需要重建数据源配置类,以替代默认的配置类 MongoProperties。

首先,创建数据源配置基类 AbstractMongoConfigure。

AbstractMongoConfigure

import com.mongodb.MongoClient; import com.mongodb.MongoClientOptions; import com.mongodb.MongoCredential; import com.mongodb.ServerAddress; import org.springframework.data.mongodb.MongoDbFactory; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoDbFactory; /** * Mongo 配置抽象类 * * @author xiepd * @date 2019/7/16 */ public abstract class AbstractMongoConfigure { private String database; private String host; private int port; private String authenticationDatabase; private String username; private char[] password; public MongoDbFactory mongoDbFactory() { MongoDbFactory factory; if (authenticationDatabase != null && username != null && password != null) { ServerAddress serverAddress = new ServerAddress(host, port); MongoCredential credential = MongoCredential.createCredential(username, authenticationDatabase, password); MongoClientOptions options = MongoClientOptions.builder().build(); factory = new SimpleMongoDbFactory(new MongoClient(serverAddress, credential, options), database); } else { factory = new SimpleMongoDbFactory(new MongoClient(host, port), database); } return factory; } public abstract MongoTemplate getMongoTemplate(); // getter & setter }

然后,创建分别对应 primary 和 secondary 的配置类 PrimaryMongoConfigure 及 SecondaryMongoConfigure

PrimaryMongoConfigure

import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Primary; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.stereotype.Component; /** * @author xiepd * @date 2019/7/16 */ @Component @ConfigurationProperties(prefix = "spring.data.mongodb.primary") @EnableMongoRepositories(basePackages = "com.panda.mongo.repository.primary", mongoTemplateRef = "primaryMongoTemplate") public class PrimaryMongoConfigure extends AbstractMongoConfigure { @Override @Primary @Bean(name = "primaryMongoTemplate") public MongoTemplate getMongoTemplate() { return new MongoTemplate(mongoDbFactory()); } }

SecondaryMongoConfigure

import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.stereotype.Component; /** * @author xiepd * @date 2019/7/16 */ @Component @ConfigurationProperties(prefix = "spring.data.mongodb.secondary") @EnableMongoRepositories(basePackages = "com.panda.mongo.repository.secondary", mongoTemplateRef = "secondaryMongoTemplate") public class SecondaryMongoConfigure extends AbstractMongoConfigure { @Override @Bean(name = "secondaryMongoTemplate") public MongoTemplate getMongoTemplate() { return new MongoTemplate(mongoDbFactory()); } }

在以上代码中,出现了多种注解,现对关键项作简要说明:

@ConfigurationProperties:声明该类为配置类,可读取配置文件中相同配置项的值。例如,设前缀 prefix 为 user,则当前类的 name 属性可取配置文件中 user.name 的值@EnableMongoRepositories:配置 repository 目录与 mongoTemplate 的对应关系,即指明某个目录下的 repository 接口采用哪个 mongoTemplate。此 mongoTemplate 与数据源一一对应@Primary:声明该数据源为主要数据源,若没有添加该注解,SpringBoot 在生成 bean 的时候会抛出异常

4. 创建实体类与接口

第四步,创建数据实体 User 与操作接口 UserRepository:

User

import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Field; /** * 用户数据实体类 */ @Document(collection = "user") public class User { @Id private String id; @Field(value = "name") private String name; @Field(value = "age") private Integer age; // getter & setter }

UserRepository

package com.panda.mongo.repository.primary; import com.panda.mongo.entity.User; import org.springframework.data.mongodb.repository.MongoRepository; /** * Created by xiepd on 2019/07/16. */ public interface UserRepository extends MongoRepository<User, String> { }

需要特别注意的是,repository 所在的目录就决定了它所对应的 mongoTemplate,不可放错目录。

5. 调用示例

最后一步,我们创建 Service 实现调用:

import com.panda.mongo.repository.primary.UserRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.stereotype.Service; import javax.annotation.Resource; /** * Created by xiepd on 2019/07/16. */ @Service public class UserService { @Autowired private UserRepository repository; @Resource(name = "primaryMongoTemplate") private MongoTemplate mongoTemplate; // CRUD method }

通常,repository 接口已经为我们预设好简单的增删改查方法,只需将 UserRepository 放置到正确的目录下,然后由 SpringBoot 注入即可。

若有复杂的业务,可直接获取 mongoTemplate 实例,然后实现其 CRUD 方法。该实例获取方式简单,通过 @Resource 注解并指明名称即可,SpringBoot 会自动从管理的 bean 中查找名称一致的 mongoTemplate 实例。


最新回复(0)