大家好!

最近一直在研究如何在springboot中如何配置多个mongodb数据源,查阅了很多网上的资料发现,很多示例都是很久以前示例了,在新版本的spring-data-mongodb-3.0.2 中已经不再支持网络上的大部分的示例了,如:基于 SimpleMongoDbFactory 的这种方已经被废弃删除了,应改用SimpleMongoClientDatabaseFactory 方式,经过一天的研究终于总结出了最新的配置方式供大家参考:

步骤如下:

导入依赖:

<!-- spring-boot 版本 -->
<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.3.2.RELEASE</version>
	<relativePath/>
</parent>

<!-- spring-boot data mongodb 依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

1.在yaml 文件中 配置两个以上mongo 集群数据源

spring:
  data:
    mongodb:
      mpc:
        uri: mongodb://用户名:密码@ip:port,ip:port/database
      saas:
        uri: mongodb://用户名:密码@ip:port,ip:port/database

2.排除springboot默认的mongo初始化机制

@SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
public class MpcExampleApplication {

    public static void main(String[] args) {
        SpringApplication.run(MpcExampleApplication.class, args);
    }

}

3.生成多个MongoTemplate 并开启Repositor 操作并指定作用于哪个package

创建mongoSaasTemplate作用于"com.sun.mpc.example.storage.mongorpst.mpc" 下的Repository 

/**
 * 初始化mcp mongoMpcTemplate
 * 如果不是多mongo数据源无需引入该配置
 * 注:开启多数据源配置需要排除springboot默认的mongo初始化机制
 * @SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
 * @author liangjian
 * @date
 */
@Slf4j
@Configuration
@EnableMongoRepositories(basePackages = "com.sun.mpc.example.storage.mongorpst.mpc", mongoTemplateRef = "mongoMpcTemplate")
public class MongoMpcTemplateConfig {

    @Value("${spring.data.mongodb.mpc.uri}")
    private String uri;

    @Primary
    @Bean(name = "mongoMpcTemplate")
    public MongoTemplate mongoMpcTemplate() throws Exception {
        log.info("-----------------------init mongoMpcTemplate success-----------------------------------");
        return new MongoTemplate(mongoMpcFactory());
    }

    @Bean
    @Primary
    public MongoDatabaseFactory mongoMpcFactory() throws Exception {
        SimpleMongoClientDatabaseFactory simpleMongoClientDbFactory = new SimpleMongoClientDatabaseFactory(uri);
        return simpleMongoClientDbFactory;
    }

}

创建mongoSaasTemplate作用于"com.sun.mpc.example.storage.mongorpst.saas" 下的Repository 

/**
 * 初始化saas mongoSaasTemplate
 * 如果不是多mongo数据源无需引入该配置
 * 注:开启多数据源配置需要排除springboot默认的mongo初始化机制
 * @SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
 * @author liangjian
 * @date
 */
@Slf4j
@Configuration
@EnableMongoRepositories(basePackages = "com.sun.mpc.example.storage.mongorpst.saas", mongoTemplateRef = "mongoSaasTemplate")
public class MongoSaasTemplateConfig {

    @Value("${spring.data.mongodb.saas.uri}")
    private String uri;

    @Primary
    @Bean(name = "mongoSaasTemplate")
    public MongoTemplate mongoSaasTemplate() throws Exception {
        log.info("-----------------------init mongoSaasTemplate success-----------------------------------");
        return new MongoTemplate(mongoSaasFactory());
    }

    @Bean
    @Primary
    public MongoDatabaseFactory mongoSaasFactory() throws Exception {
        SimpleMongoClientDatabaseFactory simpleMongoClientDbFactory = new SimpleMongoClientDatabaseFactory(uri);
        return simpleMongoClientDbFactory;
    }

}

4.包结构截图
 

springcloud mongodb分库分表 springboot mongodb多数据源_spring

5.测试类

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestPropertySource(properties={"spring.profiles.active=int"})
public class MongoRepositoryMultiSourceTest {

    @Autowired
    private MStudentTestEntityRepository mstudentTestEntityRepository;

    @Autowired
    private SStudentTestEntityRepository sstudentTestEntityRepository;


    @Test
    public void contextLoads() {

        mstudentTestEntityRepository.insert(MStudentTestEntity.builder()
                .name("woshi m")
                .age(20)
                .sex(true)
                .build());
        sstudentTestEntityRepository.insert(SStudentTestEntity.builder()
                .name("woshi s")
                .age(20)
                .sex(true)
                .build());
    }

}

最后虽然不是很详细,也没有具体说明,但是我想凡是对这块稍微有点了解跟研究的,一定能看懂,至此简单集成已经完成并且满足基本需求。

6.扩展 (选读)设置 auto_index_creation = true 自动创建索引失效问题

由于我们覆盖了 spring boot 自动装配mongo配置,导致 实体类的字段注解 @Indexed 自动创建索引失效,即下面的yml 配置不起作用。

spring:
  data:
    mongodb:
      auto-index-creation: true #自动创建索引
为了解决这个问题我对配置类做了优化如下:
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.domain.EntityScanner;
import org.springframework.boot.context.properties.PropertyMapper;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory;
import org.springframework.data.mongodb.core.convert.DbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;

import java.util.Collections;

/**
 * 初始化saas mongoSaasTemplate
 * 如果不是多mongo数据源无需引入该配置
 * 注:开启多数据源配置需要排除springboot默认的mongo初始化机制
 * @SpringBootApplication(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
 * @author liangjian
 * @date
 */
@Slf4j
@Configuration
@EnableMongoRepositories(basePackages = "com.sun.mpc.example.storage.mongorpst.saas", mongoTemplateRef = "mongoSaasTemplate")
public class MongoSaasTemplateConfig {

    @Value("${spring.data.mongodb.saas.uri}")
    private String uri;

    @Bean
    public MongoTemplate mongoSaasTemplate(MongoDatabaseFactory mongoSaasFactory, MappingMongoConverter mongoSaasConverter) throws Exception {
        log.info("-----------------------init mongoSaasTemplate success-----------------------------------");
        return new MongoTemplate(mongoSaasFactory,mongoSaasConverter);
    }

    @Bean
    public MongoDatabaseFactory mongoSaasFactory()  throws Exception {
        SimpleMongoClientDatabaseFactory simpleMongoClientDbFactory = new SimpleMongoClientDatabaseFactory(uri);
        return simpleMongoClientDbFactory;
    }

    /**
     * 设置AutoIndexCreation 等于 true 自动创建索引
     * @param mongoSaasFactory
     * @return org.springframework.data.mongodb.core.convert.MappingMongoConverter
     * @author liangjian
     */
    @Bean
    MappingMongoConverter mongoSaasConverter(MongoDatabaseFactory mongoSaasFactory, ApplicationContext applicationContext) throws Exception {
        MongoCustomConversions conversions = new MongoCustomConversions(Collections.emptyList());
        DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoSaasFactory);
        PropertyMapper mapper = PropertyMapper.get().alwaysApplyingWhenNonNull();
        MongoMappingContext context = new MongoMappingContext();
        mapper.from(true).to(context::setAutoIndexCreation);
        context.setInitialEntitySet(new EntityScanner(applicationContext).scan(Document.class, Persistent.class));
        context.setSimpleTypeHolder(conversions.getSimpleTypeHolder());
        MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
        mappingConverter.setCustomConversions(conversions);
        return mappingConverter;
    }

}

 注意这段代码:

  mapper.from(true).to(context::setAutoIndexCreation);  我写死为true 相当于无需yml配置即可实现自动创建索引,读者可根据实际情况,选择从yaml 中读取  auto-index-creation: true 配置,实现动态配置

完结~~~