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

相关推荐
LUCIAZZZ2 小时前
TCP基本入门-简单认识一下什么是TCP
java·网络·后端·网络协议·tcp/ip·计算机网络·spring
_未知_开摆2 小时前
2020年蓝桥杯Java B组第二场题目+部分个人解析
java·经验分享·后端·程序人生·蓝桥杯
m0_748234523 小时前
Spring Boot整合WebSocket
spring boot·后端·websocket
m0_748232393 小时前
SpringBoot Maven 项目 pom 中的 plugin 插件用法整理
spring boot·后端·maven
Asthenia04123 小时前
深入解析消息持久化实现机制:基于 `LocalMqBrokerPersist` 的简化实现
后端
yuhaiqiang4 小时前
解密如何快速搭建一套虚拟商品交易系统,推荐这个神奇的开源项目
后端
xidianhuihui4 小时前
go如何排查某个依赖是哪里引入的
开发语言·后端·golang
姜来可期4 小时前
【Golang】go语言异常处理快速学习
开发语言·笔记·后端·学习·golang
Toormi5 小时前
Go 1.24版本在性能方面有哪些提升?
开发语言·后端·golang
yqcoder5 小时前
Express + MongoDB 实现用户登出
数据库·mongodb·express