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

news2025/3/4 11:36:50

       要想在同一个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("用户名");
    }
}

结果如图:

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

参考:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2309471.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++20 标准化有符号整数:迈向更可预测的整数运算

文章目录 一、背景&#xff1a;为什么需要标准化&#xff1f;二、2 的补码&#xff1a;原理与优势&#xff08;一&#xff09;2 的补码原理&#xff08;二&#xff09;2 的补码的优势 三、C20 的变化&#xff1a;明确 2 的补码四、如何利用这一特性优化代码&#xff08;一&…

npm ERR! code 128 npm ERR! An unknown git error occurred

【问题描述】 【问题解决】 管理员运行cmd&#xff08;右键window --> 选择终端管理员&#xff09; 执行命令 git config --global url.“https://”.insteadOf ssh://git cd 到项目目录 重新执行npm install 个人原因&#xff0c;这里执行npm install --registryhttps:…

泵吸式激光可燃气体监测仪:快速精准守护燃气管网安全

在城市化进程加速的今天&#xff0c;燃气泄漏、地下管网老化等问题时刻威胁着城市安全。如何实现精准、高效的可燃气体监测&#xff0c;守护“城市生命线”&#xff0c;成为新型基础设施建设的核心课题。泵吸式激光可燃气体监测仪&#xff0c;以创新科技赋能安全监测&#xff0…

Stiring-PDF:开源免费的PDF文件处理软件

Stiring-PDF是一款开源免费且比较好用的PDF文件处理工具。 Stiring-PDF官网网址为&#xff1a;https://www.stiringpdf.com/。Stiring-PDF是一款专业的PDF文件处理工具&#xff0c;支持Windows和macOS操作系统&#xff1b;提供丰富的PDF编辑和转换功能&#xff0c;适用于日常工…

Cherno C++ P60 为什么不用using namespace std

这篇文章我们讲一下之前写代码的时候的一个习惯&#xff0c;也就是不使用using namespace std。如果我们接触过最早的C教程&#xff0c;那么第一节课都会让我们写如下的代码&#xff1a; #include<iostream>using namespace std;int main() {cout << "Hello …

大模型微调实验记录(一)数据探索

文章目录 概要整体架构流程前期的技术探索技术构造技术细节小结 概要 根据之前博客使用的docker技术&#xff0c;如果换公司了&#xff0c;我可能就要重新搭建环境了&#xff0c;哎&#xff0c;公司没资源给我&#xff0c;给我一台带不走的电脑&#xff0c;哎&#xff0c;这可…

JavaWeb-社区版Idea安装配置

idea配置 一&#xff0c;下载idea社区版 百度搜索IntelliJ IDEA&#xff0c;点击下载链接。 二&#xff0c;全局配置 前提安装好jdk&#xff0c;这一步不再赘述。进入引导页&#xff0c;把可以配置的东西都先配置上&#xff0c;这个配置是全局的&#xff0c;省的之后&#…

商城系统单商户开源版源码

环境配置 1.软件安装 宝塔安装系统软件:Nginx、MySQL5.6、PHP( PHP用7.1-7.4版本)、phpMyAdmin(Web端MySQL管理工具)。 2.配置mysql 设置mysql&#xff0c;在已安装的软件里面找到 mysql点击进行设置 3.修改sql-mode 选择左侧配置修改&#xff0c;找到里面的sql-mode&…

Python PDF文件拆分-详解

目录 使用工具 将PDF按页数拆分 将PDF的每一页拆分为单独的文件 将PDF按指定页数拆分 根据页码范围拆分PDF 根据指定内容拆分PDF 将PDF的一页拆分为多页 在日常生活中&#xff0c;我们常常会遇到大型的PDF文件&#xff0c;这些文件可能难以发送、管理和查阅。将PDF拆分成…

ubuntu部署gitlab-ce及数据迁移

ubuntu部署gitlab-ce及数据迁移 进行前梳理: 在esxi7.0 Update 3 基础上使用 ubuntu22.04.5-server系统对 gitlab-ce 16.10进行部署,以及将gitlab-ee 16.9 数据进行迁移到gitlab-ce 16.10 进行后总结: 起初安装了极狐17.8.3-jh 版本(不支持全局中文,就没用了) …

Y3学习打卡

网络结构图 YOLOv5配置了4种不同大小的网络模型&#xff0c;分别是YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x&#xff0c;其中 YOLOv5s 是网络深度和宽度最小但检测速度最快的模型&#xff0c;其他3种模型都是在YOLOv5s的基础上不断加深、加宽网络使得网络规模扩大&#xff0c;在增强…

英码科技携昇腾DeepSeek大模型一体机亮相第三届北京人工智能产业创新发展大会

2025年2月28日&#xff0c;第三届北京人工智能产业创新发展大会在国家会议中心隆重开幕。本届大会以"好用、易用、愿用——以突破性创新加速AI赋能千行百业”为主题&#xff0c;重点展示人工智能技术创新成果与产业化应用实践。作为昇腾生态的APN伙伴&#xff0c;英码科技…

JS禁止web页面调试

前言 由于前端在页面渲染的过程中 会调用很多后端的接口&#xff0c;而有些接口是不希望别人看到的&#xff0c;所以前端调用后端接口的行为动作就需要做一个隐藏。 禁用右键菜单 document.oncontextmenu function() {console.log("禁用右键菜单");return false;…

modbus 协议的学习,谢谢老师

&#xff08;1&#xff09;谢谢这位老师 &#xff0c;谢谢老师的教导 &#xff08;2&#xff09; 谢谢

题解 | 牛客周赛82 Java ABCDEF

目录 题目地址 做题情况 A 题 B 题 C 题 D 题 E 题 F 题 牛客竞赛主页 题目地址 牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ 做题情况 A 题 判断字符串第一个字符和第三个字符是否相等 import java.io.*; import java.math.*; import java.u…

命名管道——进程间通信

个人主页&#xff1a;敲上瘾-CSDN博客 匿名管道&#xff1a;进程池的制作&#xff08;linux进程间通信&#xff0c;匿名管道... ...&#xff09;-CSDN博客 一、命名管道的使用 1.创建命名管道 1.1.在命令行中&#xff1a; 创建&#xff1a; mkfifo 管道名 删除&#xff1a…

高频 SQL 50 题(基础版)_1141. 查询近30天活跃用户数

1141. 查询近30天活跃用户数 select activity_date day,count(distinct user_id) active_users from Activity where (activity_date<2019-07-27 and activity_date>DATE_sub(2019-07-27,INTERVAL 30 DAY)) group by(activity_date)

Yocto + 树莓派摄像头驱动完整指南

—— 从驱动配置、Yocto 构建&#xff0c;到 OpenCV 实战 在树莓派上运行摄像头&#xff0c;在官方的 Raspberry Pi OS 可能很简单&#xff0c;但在 Yocto 项目中&#xff0c;需要手动配置驱动、设备树、软件依赖 才能确保摄像头正常工作。本篇文章从 BSP 驱动配置、Yocto 关键…

计算最大海岛面积

最大海岛面积问题的不同解法 问题举例 给定一个包含了一些 0 和 1 的非空二维数组 matrix 。 一个岛屿是由一些相邻的 1 (代表土地) 构成的组合&#xff0c;这里的「相邻」要求两个 1 必须在水平或者竖直方向上相邻。你可以假设matrix的四个边缘都被 0&#xff08;代表水&am…

Spark核心之02:RDD、算子分类、常用算子

spark内存计算框架 一、目标 深入理解RDD弹性分布式数据集底层原理掌握RDD弹性分布式数据集的常用算子操作 二、要点 ⭐️1. RDD是什么 RDD&#xff08;Resilient Distributed Dataset&#xff09;叫做**弹性分布式数据集&#xff0c;是Spark中最基本的数据抽象&#xff0c…