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使用这些配置。
java 复制代码
@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使用这些配置。
java 复制代码
@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

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

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

java 复制代码
@Repository
public interface UserInfoRepository extends MongoRepository<UserInfoEntity, String> {
    List<UserInfoEntity> findByUserNameLike(String username);
    List<UserInfoEntity> findByUserName(String username);
}
  • 实现service

使用Repository实现的访问的service

java 复制代码
@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

java 复制代码
@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:

bash 复制代码
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

测试类:

java 复制代码
@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("用户名");
    }
}

结果如图:

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

参考:

http://www.voidcn.com/article/p-zqjtjvhm-bvu.html

相关推荐
做运维的阿瑞2 小时前
Python零基础入门:30分钟掌握核心语法与实战应用
开发语言·后端·python·算法·系统架构
Q_Q19632884752 小时前
python+spring boot洪涝灾害应急信息管理系统 灾情上报 预警发布 应急资源调度 灾情图表展示系统
开发语言·spring boot·python·django·flask·node.js·php
猿究院-陆昱泽3 小时前
Redis 五大核心数据结构知识点梳理
redis·后端·中间件
yuriy.wang3 小时前
Spring IOC源码篇五 核心方法obtainFreshBeanFactory.doLoadBeanDefinitions
java·后端·spring
咖啡教室5 小时前
程序员应该掌握的网络命令telnet、ping和curl
运维·后端
你的人类朋友6 小时前
Let‘s Encrypt 免费获取 SSL、TLS 证书的原理
后端
老葱头蒸鸡6 小时前
(14)ASP.NET Core2.2 中的日志记录
后端·asp.net
李昊哲小课7 小时前
Spring Boot 基础教程
java·大数据·spring boot·后端
码事漫谈7 小时前
C++内存越界的幽灵:为什么代码运行正常,free时却崩溃了?
后端
诺青2357 小时前
MongoDB副本集
数据库·mongodb