SpringBoot整合mongoDB并自定义连接池实现多数据源配置教程

 更新时间:2025年11月19日 09:25:01   作者:码上走人  
本文介绍了如何在Spring Boot项目中整合MongoDB并实现多数据源配置,通过自定义连接池和使用`@EnableMongoRepositories`注解,实现了两个MongoDB数据源的管理和使用

SpringBoot整合mongoDB并自定义连接池实现多数据源配置

要想在同一个springboot项目中使用多个数据源,最主要是每个数据源都有自己的mongoTemplate和MongoDbFactory。mongoTemplate和MongoDbFactory是负责对数据源进行交互的并管理链接的。

spring提供了一个注解@EnableMongoRepositories 用来注释在某些路径下的MongoRepositor实现类使用哪个MongoTemplate实例。当然如果我们是直接使用MongoTemplate操作,那么只需要使用于数据库对应的MongoTemplate即可。

代码结果如下:

首先实现两个config,实现对MongoTemplate和MongoDbFactory的配置

mongoTemplate1和mongoDbFactory1

  • 并使用@EnableMongoRepositories指定在“com.zhong.springdemo.mangodbdome.mongodb1”目录下的MongoRepositor使用这些配置。
@Configuration
//指定com.zhong.springdemo.mangodbdome.mongodb1路径下的MongoRepository使用 容器中的  mongoTemplate1实例
@EnableMongoRepositories(mongoTemplateRef = "mongoTemplate1",basePackages = {"com.zhong.springdemo.mangodbdome.mongodb1"})
public class MongoDbConfigure {

    @Autowired
    MongoDbFactoryProperties mongoDbFactoryProperties;

    /**
     * 自定义 mongoTemplate 实现多数据源配置
     */

    @Bean("mongoTemplate1")
    public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory1, MongoMappingContext context){
        MappingMongoConverter mappingMongoConverter = mappingMongoConverter(mongoDbFactory1, context);
        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory1, mappingMongoConverter);
        return mongoTemplate;
    }


    /**
     * 自定义mongo连接池
     * @param properties 私有配置
     * @return
     */
    @Bean("mongoDbFactory1")
    public MongoDbFactory mongoDbFactory(MongoDbProperties properties) {
        //创建客户端参数
        MongoClientOptions options = mongoClientOptions(properties);

        //解析地址
        List<ServerAddress> serverAddresses = new ArrayList<>();
        for (String address : properties.getAddress().split(",")) {
            String[] hostAndPort = address.split(":");
            String host = hostAndPort[0];
            Integer port = Integer.parseInt(hostAndPort[1]);
            ServerAddress serverAddress = new ServerAddress(host, port);
            serverAddresses.add(serverAddress);
        }

        //创建认证客户端
        MongoCredential mongoCredential = MongoCredential.createScramSha1Credential(properties.getUsername(),
                properties.getAuthenticationDatabase() != null ? properties.getAuthenticationDatabase() : properties.getDatabase(),
                properties.getPassword().toCharArray());

        MongoClient mongoClient = new MongoClient(serverAddresses.get(0), mongoCredential, options);
        //集群模式
        if (serverAddresses.size() > 1) {
            mongoClient = new MongoClient(serverAddresses, mongoCredential, null);
        }
        /** 创建非认证客户端*/
        //MongoClient mongoClient = new MongoClient(serverAddresses, mongoClientOptions);
        return new SimpleMongoDbFactory(mongoClient, properties.getDatabase());
    }

    /**
     * mongo客户端参数配置
     * @return
     */
    private MongoClientOptions mongoClientOptions(MongoDbProperties properties) {
        MongoDbFactoryProperties factoryProperties = this.mongoDbFactoryProperties;
        return MongoClientOptions.builder()
                .connectTimeout(factoryProperties.getConnectionTimeoutMs())
                .socketTimeout(factoryProperties.getReadTimeoutMs()).applicationName(factoryProperties.getApplicationName())
                .heartbeatConnectTimeout(factoryProperties.getHeartbeatConnectionTimeoutMs())
                .heartbeatSocketTimeout(factoryProperties.getHeartbeatReadTimeoutMs())
                .heartbeatFrequency(factoryProperties.getHeartbeatFrequencyMs())
                .minHeartbeatFrequency(factoryProperties.getMinHeartbeatFrequencyMs())
                .maxConnectionIdleTime(factoryProperties.getConnectionMaxIdleTimeMs())
                .maxConnectionLifeTime(factoryProperties.getConnectionMaxLifeTimeMs())
                .maxWaitTime(factoryProperties.getPoolMaxWaitTimeMs())
                .connectionsPerHost(factoryProperties.getConnectionsPerHost())
                .threadsAllowedToBlockForConnectionMultiplier(
                        factoryProperties.getThreadsAllowedToBlockForConnectionMultiplier())
                .minConnectionsPerHost(factoryProperties.getMinConnectionsPerHost()).build();
    }

    /**
     * monogo 转换器
     * @return
     */
    private MappingMongoConverter mappingMongoConverter(MongoDbFactory mongoDbFactory1, MongoMappingContext context) {
        DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDbFactory1);
        MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
        //此处是去除插入数据库的 _class 字段
        mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
        return mappingConverter;
    }
}

mongoTemplate2和mongoDbFactory2

  • 并使用@EnableMongoRepositories指定在“com.zhong.springdemo.mangodbdome.mongodb2”目录下的MongoRepositor使用这些配置。
@Configuration
//指定com.zhong.springdemo.mangodbdome.mongodb2路径下的MongoRepository使用 容器中的  mongoTemplate2实例
@EnableMongoRepositories(mongoTemplateRef = "mongoTemplate2",basePackages = {"com.zhong.springdemo.mangodbdome.mongodb2"})
public class MongoDbConfigure2 {

    @Autowired
    MongoDbFactoryProperties mongoDbFactoryProperties;

    /**
     * 自定义 mongoTemplate 实现多数据源配置
     */

    @Bean("mongoTemplate2")
    public MongoTemplate mongoTemplate(MongoDbFactory mongoDbFactory2, MongoMappingContext context){
        MappingMongoConverter mappingMongoConverter = mappingMongoConverter(mongoDbFactory2, context);
        MongoTemplate mongoTemplate = new MongoTemplate(mongoDbFactory2, mappingMongoConverter);
        return mongoTemplate;
    }

    /**
     * 自定义mongo连接池
     * @param properties 私有配置
     * @return
     */
    @Bean("mongoDbFactory2")
    public MongoDbFactory mongoDbFactory2(MongoDbProperties2 properties) {
        //创建客户端参数
        MongoClientOptions options = mongoClientOptions(properties);

        //解析地址
        List<ServerAddress> serverAddresses = new ArrayList<>();
        for (String address : properties.getAddress().split(",")) {
            String[] hostAndPort = address.split(":");
            String host = hostAndPort[0];
            Integer port = Integer.parseInt(hostAndPort[1]);
            ServerAddress serverAddress = new ServerAddress(host, port);
            serverAddresses.add(serverAddress);
        }

        //创建认证客户端
        MongoCredential mongoCredential = MongoCredential.createScramSha1Credential(properties.getUsername(),
                properties.getAuthenticationDatabase() != null ? properties.getAuthenticationDatabase() : properties.getDatabase(),
                properties.getPassword().toCharArray());

        MongoClient mongoClient = new MongoClient(serverAddresses.get(0), mongoCredential, options);
        //集群模式
        if (serverAddresses.size() > 1) {
            mongoClient = new MongoClient(serverAddresses, mongoCredential, null);
        }
        /** 创建非认证客户端*/
        //MongoClient mongoClient = new MongoClient(serverAddresses, mongoClientOptions);
        return new SimpleMongoDbFactory(mongoClient, properties.getDatabase());
    }

    /**
     * mongo客户端参数配置
     * @return
     */
    private MongoClientOptions mongoClientOptions(MongoDbProperties2 properties) {
        MongoDbFactoryProperties factoryProperties = this.mongoDbFactoryProperties;
        return MongoClientOptions.builder()
                .connectTimeout(factoryProperties.getConnectionTimeoutMs())
                .socketTimeout(factoryProperties.getReadTimeoutMs()).applicationName(factoryProperties.getApplicationName())
                .heartbeatConnectTimeout(factoryProperties.getHeartbeatConnectionTimeoutMs())
                .heartbeatSocketTimeout(factoryProperties.getHeartbeatReadTimeoutMs())
                .heartbeatFrequency(factoryProperties.getHeartbeatFrequencyMs())
                .minHeartbeatFrequency(factoryProperties.getMinHeartbeatFrequencyMs())
                .maxConnectionIdleTime(factoryProperties.getConnectionMaxIdleTimeMs())
                .maxConnectionLifeTime(factoryProperties.getConnectionMaxLifeTimeMs())
                .maxWaitTime(factoryProperties.getPoolMaxWaitTimeMs())
                .connectionsPerHost(factoryProperties.getConnectionsPerHost())
                .threadsAllowedToBlockForConnectionMultiplier(
                        factoryProperties.getThreadsAllowedToBlockForConnectionMultiplier())
                .minConnectionsPerHost(factoryProperties.getMinConnectionsPerHost()).build();
    }

    /**
     * monogo 转换器
     * @return
     */
    private MappingMongoConverter mappingMongoConverter(MongoDbFactory factory, MongoMappingContext context) {
        DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory);
        MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, context);
        //此处是去除插入数据库的 _class 字段
        mappingConverter.setTypeMapper(new DefaultMongoTypeMapper(null));
        return mappingConverter;
    }
}

Repository实现

实现mongdb1下的repository---UserInfoTestRepository,UserInfoTestRepository使用的是mongoTemplate2和mongoDbFactory2

@Repository
public interface UserInfoTestRepository extends MongoRepository<UserInfoEntity, String> {
    List<UserInfoEntity> findByUserNameLike(String username);
    List<UserInfoEntity> findByUserName(String username);
}

实现mongdb2下的repository---UserInfRepository,UserInfRepository使用的是mongoTemplate1和mongoDbFactory1

@Repository
public interface UserInfoRepository extends MongoRepository<UserInfoEntity, String> {
    List<UserInfoEntity> findByUserNameLike(String username);
    List<UserInfoEntity> findByUserName(String username);
}

实现service

使用Repository实现的访问的service

@Service
public class UserInfoServiceImpl implements UserInfoService {
    @Autowired
    private UserInfoRepository userInfoRepository;

    @Autowired
    private UserInfoTestRepository userInfoTestRepository;

    @Override
    public List<UserInfoEntity> findByUserName(String userName){
        return userInfoRepository.findByUserName(userName);
    }

    @Override
    public int saveTestUser(List<UserInfoDto> userInfoDtos) {
        List<UserInfoEntity> userInfoEntities = Lists.newArrayList();
        for(UserInfoDto userInfoDto : userInfoDtos){
            UserInfoEntity userInfoEntity = new UserInfoEntity();
            BeanUtils.copyProperties(userInfoDto, userInfoEntity);
            userInfoEntities.add(userInfoEntity);
        }

        userInfoTestRepository.saveAll(userInfoEntities);
        return userInfoEntities.size();
    }

    @Override
    public int saveUser(List<UserInfoDto> userInfoDtos) {
        List<UserInfoEntity> userInfoEntities = Lists.newArrayList();
        for(UserInfoDto userInfoDto : userInfoDtos){
            UserInfoEntity userInfoEntity = new UserInfoEntity();
            BeanUtils.copyProperties(userInfoDto, userInfoEntity);
            userInfoEntities.add(userInfoEntity);
        }

        userInfoRepository.saveAll(userInfoEntities);
        return userInfoEntities.size();
    }
}

使用MongoTemplate实现的访问的service

@Service
public class UserInfoMongoTemplateServiceImpl implements UserInfoMongoTemplateService {
    @Autowired
    MongoTemplate mongoTemplate1;

    @Autowired
    MongoTemplate mongoTemplate2;

    @Override
    public List<UserInfoEntity> findByUserName(String userName){
        Criteria criteria = Criteria.where("user_name").is(userName);
        return mongoTemplate1.find(getQueryFilter(criteria), UserInfoEntity.class);
    }

    @Override
    public int saveTestUser(List<UserInfoDto> userInfoDtos) {
        List<UserInfoEntity> userInfoEntities = Lists.newArrayList();
        for(UserInfoDto userInfoDto : userInfoDtos){
            UserInfoEntity userInfoEntity = new UserInfoEntity();
            BeanUtils.copyProperties(userInfoDto, userInfoEntity);
            userInfoEntities.add(userInfoEntity);
        }

        mongoTemplate1.insert(userInfoEntities, UserInfoEntity.class);
        return userInfoEntities.size();
    }

    @Override
    public int saveUser(List<UserInfoDto> userInfoDtos) {
        List<UserInfoEntity> userInfoEntities = Lists.newArrayList();
        for(UserInfoDto userInfoDto : userInfoDtos){
            UserInfoEntity userInfoEntity = new UserInfoEntity();
            BeanUtils.copyProperties(userInfoDto, userInfoEntity);
            userInfoEntities.add(userInfoEntity);
        }

        mongoTemplate2.insert(userInfoEntities, UserInfoEntity.class);
        return userInfoEntities.size();
    }

    private Query getQueryFilter(Criteria criteria, String  ...parms) {
        criteria = criteria == null ? new Criteria() : criteria;
        Query query = new Query();
        query.addCriteria(criteria);
        if(parms != null && parms.length > 0){
            Field fields = query.fields();
            for(String parm : parms){
                fields.include(parm);
            }
        }
        return query;
    }
}

两个数据源信息配置properties.yaml:

zhong:
  #自定义的mongodb测试
  data:
    mongodb:
      database: zhong-mongo
      password: 123456
      address: 127.0.0.1:27017
      username: admin
      authenticationDatabase: admin
    mongodb2:
      database: test-mongo
      password: 123456
      address: 127.0.0.1:27017
      username: admin
      authenticationDatabase: admin

测试类:

@Component
public class MongoStartTest implements CommandLineRunner {

    @Autowired
    UserInfoService userInfoService;

    @Autowired
    UserInfoMongoTemplateService userInfoMongoTemplateService;

    @Override
    public void run(String... args) throws Exception {
        for(int i = 0; i < 25; i++){
            UserInfoDto userInfoDto = new UserInfoDto();
            userInfoDto.setUserId(UUID.randomUUID().toString().replace("-", ""));
            userInfoDto.setUserName("用户名" + i);
            userInfoDto.setAuthor("登录名" + i);
            userInfoDto.setPwd("123456" + i);
            userInfoDto.setCreateTime(new Date());
            userInfoService.saveTestUser(Lists.newArrayList(userInfoDto));
            userInfoService.saveUser(Lists.newArrayList(userInfoDto));
        }

        for(int i = 100; i < 125; i++){
            UserInfoDto userInfoDto = new UserInfoDto();
            userInfoDto.setUserId(UUID.randomUUID().toString().replace("-", ""));
            userInfoDto.setUserName("用户名" + i);
            userInfoDto.setAuthor("登录名" + i);
            userInfoDto.setPwd("123456" + i);
            userInfoDto.setCreateTime(new Date());
            userInfoMongoTemplateService.saveTestUser(Lists.newArrayList(userInfoDto));
            userInfoMongoTemplateService.saveUser(Lists.newArrayList(userInfoDto));
        }
        userInfoService.findByUserName("用户名");

        userInfoMongoTemplateService.findByUserName("用户名");
    }
}

结果如图:

数据的确被插入到不同的库中了

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 使用 Java8 实现观察者模式的方法(下)

    使用 Java8 实现观察者模式的方法(下)

    这篇文章主要介绍了使用 Java8 实现观察者模式的方法(下)的相关资料,需要的朋友可以参考下
    2016-02-02
  • Java之 TreeSet的详细使用说明

    Java之 TreeSet的详细使用说明

    这篇文章主要介绍了Java之 TreeSet的详细使用说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • Java关键字instanceof用法及实现策略

    Java关键字instanceof用法及实现策略

    instanceof 运算符是用来在运行时判断对象是否是指定类及其父类的一个实例。这篇文章主要介绍了Java关键字instanceof用法解析,需要的朋友可以参考下
    2020-08-08
  • Idea启动SpringBoot程序报错:Veb server failed to start. Port 8082 was already in use;端口冲突的原理与解决方案

    Idea启动SpringBoot程序报错:Veb server failed to&nbs

    这篇文章主要介绍了Idea启动SpringBoot程序报错:Veb server failed to start. Port 8082 was already in use;端口冲突的原理与解决方案,文中通过代码示例介绍的非常详细,需要的朋友可以参考下
    2024-10-10
  • 使用MyBatis返回其它类对象的字段处理

    使用MyBatis返回其它类对象的字段处理

    这篇文章主要介绍了使用MyBatis返回其它类对象的字段处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-08-08
  • 使用Java DOM解析器修改XML文件内容的操作方法

    使用Java DOM解析器修改XML文件内容的操作方法

    在Java中,XML文件的解析和修改可以通过多种方法实现,其中DOM(Document Object Model)是一种常用的方式,在本文中,我们将介绍如何使用Java DOM解析器修改XML文件中的内容,并给出一个具体的示例,需要的朋友可以参考下
    2024-08-08
  • Springboot整合Rabbitmq之Confirm和Return机制

    Springboot整合Rabbitmq之Confirm和Return机制

    这篇文章主要介绍了Springboot整合Rabbitmq之Confirm和Return详解,本篇重点进行Confirm 机制和Return 机制的实现和说明,通过实例代码相结合给大家详细介绍,对Springboot整合Rabbitmq相关知识感兴趣的朋友一起看看吧
    2022-02-02
  • 一文详解Spring security框架的使用

    一文详解Spring security框架的使用

    Spring Security是一个基于Spring框架的安全认证和授权框架,它提供了一套全面的安全解决方案,可以在Web应用、移动应用和Web服务等不同场景下使用。本文就来详细聊聊它的使用吧
    2023-03-03
  • 浅谈java实现重载的方法

    浅谈java实现重载的方法

    方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。重载Overloading是一个类中多态性的一种表现。Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。
    2015-09-09
  • springBoot整合jwt实现token令牌认证的示例代码

    springBoot整合jwt实现token令牌认证的示例代码

    实施Token验证的方法挺多的,还有一些标准方法,比如JWT,本文主要介绍了springBoot整合jwt实现token令牌认证的示例代码,具有一定的参考价值,感兴趣的可以了解一下
    2024-08-08

最新评论