SpriingBoot整合MongoDB多数据源
背景:
MongoDB多数据源:springboot为3以上版本,spring-boot-starter-data-mongodb低版本MongoDBFactory已过时,
改为MongoDatabaseFactory。
1、pom引入:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId></dependency>

2、结构:

3、连接配置
spring:data:mongodb:primary:uri: mongodb://admin:admin!8@192.168.10.112:27017/kuname?authSource=admin&readPreference=primary&appname=MongoDB Compass Community&ssl=false
4、具体内容
package com.hh.framework.config;import com.hh.framework.page.MongoPageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.convert.MongoConverter;/*** @Description:mongo监听 新增时消除默认添加的 _class 字段保存实体类类型**/
@Configuration
public class ApplicationReadyListener implements ApplicationListener<ContextRefreshedEvent> {@Autowired@Qualifier("primaryMongo")MongoTemplate primaryMongoTemplate;/*@Autowired@Qualifier("secondaryMongo")MongoTemplate secondaryMongoTemplate;
*/private static final String TYPEKEY = "_class";@Overridepublic void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {MongoConverter converter = primaryMongoTemplate.getConverter();if (converter.getTypeMapper().isTypeKey(TYPEKEY)) {((MappingMongoConverter) converter).setTypeMapper(new DefaultMongoTypeMapper(null));}/* MongoConverter converter2 = secondaryMongoTemplate.getConverter();if (converter2.getTypeMapper().isTypeKey(TYPEKEY)) {((MappingMongoConverter) converter2).setTypeMapper(new DefaultMongoTypeMapper(null));}*/}@Beanpublic MongoPageHelper mongoPageHelper() {return new MongoPageHelper(primaryMongoTemplate);}}
package com.hh.framework.config;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.MongoDatabaseFactory;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver;
import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper;
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;@Configuration
public class MongoDbConfig {@AutowiredMongoDatabaseFactory mongoDatabaseFactory;public @Bean MongoTemplate mongoTemplate() throws Exception {//remove _class(insert数据时,mongodb默认生成_class字段)MappingMongoConverter converter = new MappingMongoConverter(new DefaultDbRefResolver(mongoDatabaseFactory), new MongoMappingContext());converter.setTypeMapper(new DefaultMongoTypeMapper(null));return new MongoTemplate(mongoDatabaseFactory, converter);}}
package com.hh.framework.config;import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;/*** @Description:mongo连接配置类**/
@Configuration
public class MongoInit {@Bean(name = "primaryMongoProperties")@Primary@ConfigurationProperties(prefix = "spring.data.mongodb.primary")public MongoProperties statisMongoProperties() {System.out.println("-------------------- primaryMongoProperties init ---------------------");return new MongoProperties();}/* @Bean(name = "secondaryMongoProperties")@ConfigurationProperties(prefix = "spring.data.mongodb.secondary")public MongoProperties twoMongoProperties() {System.out.println("-------------------- secondaryMongoProperties init ---------------------");return new MongoProperties();}*/}
package com.hh.framework.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
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.repository.config.EnableMongoRepositories;/*** @Description:monngo第一个数据源:primary**/
@Slf4j
@Configuration
//jar中含有此类,但此处引入冒红,不影响使用
@EnableMongoRepositories( basePackages = "com.hh.framework.entity.primary",mongoTemplateRef = "primary")
public class PrimaryMongoTemplate {@Autowired@Qualifier("primaryMongoProperties")private MongoProperties primaryMongoProperties;@Primary@Bean(name = "primaryMongo") //第一个数据源名字oneMongopublic MongoTemplate primaryMongoTemplate() {try {log.info("primaryMongoProperties:" + primaryMongoProperties.getUri());return new MongoTemplate(mongoDatabaseFactory(primaryMongoProperties));} catch (Exception e) {e.printStackTrace();}return null;}@Bean@Primarypublic MongoDatabaseFactory mongoDatabaseFactory(MongoProperties mongoProperties) {return new SimpleMongoClientDatabaseFactory(mongoProperties.getUri());}}
package com.hh.framework.config;/*import com.mongodb.MongoClientURI;*/
/*import org.springframework.data.mongodb.core.SimpleMongoDbFactory;*/
/*
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
*//*** @Description: mongo第二个数据源:secondary**/
/*
@Configuration
@EnableMongoRepositories(basePackages = "com.hh.framework.entity.secondary",mongoTemplateRef = "secondary")*/
public class SecondaryMongoTemplate {/*@Autowired@Qualifier("secondaryMongoProperties")private MongoProperties secondaryMongoProperties;@Primary@Bean(name = "secondaryMongo") //第二个数据源名字public MongoTemplate primaryMongoTemplate() {try {log.info("secondaryMongoProperties:" + secondaryMongoProperties.getUri());return new MongoTemplate(mongoDatabaseFactory(secondaryMongoProperties));} catch (Exception e) {e.printStackTrace();}return null;}@Bean@Primarypublic MongoDatabaseFactory mongoDatabaseFactory(MongoProperties mongoProperties) {return new SimpleMongoClientDatabaseFactory(mongoProperties.getUri());}*/
}
package com.hh.framework.entity.primary;import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;import java.util.Date;@Document(collection = "t_city")
@Data
public class CityEntity {private String id;private String code;private String name;
}
5、以下为工具类:
package com.hh.framework.page;import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;/*** MongoDB分页查询工具类.**/
@Component
public class MongoPageHelper {public static final int FIRST_PAGE_NUM = 1;public static final String ID = "_id";private final MongoTemplate mongoTemplate;@Autowiredpublic MongoPageHelper(MongoTemplate mongoTemplate) {this.mongoTemplate = mongoTemplate;}/*** 分页查询,直接返回集合类型的结果.** @see MongoPageHelper#pageQuery(Query,* Class, Function, Integer, Integer,* String)*/public <T> MongoPageResult<T> pageQuery(Query query, Class<T> entityClass, Integer pageSize,Integer pageNum) {return pageQuery(query, entityClass, Function.identity(), pageSize, pageNum, null);}/*** 分页查询,不考虑条件分页,直接使用skip-limit来分页.** @see MongoPageHelper#pageQuery(Query,* Class, Function, Integer, Integer,* String)*/public <T, R> MongoPageResult<R> pageQuery(Query query, Class<T> entityClass, Function<T, R> mapper,Integer pageSize, Integer pageNum) {return pageQuery(query, entityClass, mapper, pageSize, pageNum, null);}/*** 分页查询.** @param query Mongo Query对象,构造你自己的查询条件.* @param entityClass Mongo collection定义的entity class,用来确定查询哪个集合.* @param mapper 映射器,你从db查出来的list的元素类型是entityClass, 如果你想要转换成另一个对象,比如去掉敏感字段等,可以使用mapper来决定如何转换.* @param pageSize 分页的大小.* @param pageNum 当前页.* @param lastId 条件分页参数, 区别于skip-limit,采用find(_id>lastId).limit分页.* 如果不跳页,像朋友圈,微博这样下拉刷新的分页需求,需要传递上一页的最后一条记录的ObjectId。 如果是null,则返回pageNum那一页.* @param <T> collection定义的class类型.* @param <R> 最终返回时,展现给页面时的一条记录的类型。* @return PageResult,一个封装page信息的对象.*/public <T, R> MongoPageResult<R> pageQuery(Query query, Class<T> entityClass, Function<T, R> mapper,Integer pageSize, Integer pageNum, String lastId) {//分页逻辑long total = mongoTemplate.count(query, entityClass);final Integer pages = (int) Math.ceil(total / (double) pageSize);if (pageNum <= 0 || pageNum > pages) {pageNum = FIRST_PAGE_NUM;}final Criteria criteria = new Criteria();if (StringUtils.isNotBlank(lastId)) {if (pageNum != FIRST_PAGE_NUM) {criteria.and(ID).gt(new ObjectId(lastId));}query.limit(pageSize);} else {int skip = pageSize * (pageNum - 1);query.skip(skip).limit(pageSize);}final List<T> entityList = mongoTemplate.find(query.addCriteria(criteria).with(Sort.by(Lists.newArrayList(new Order(Direction.ASC, ID)))),entityClass);final MongoPageResult<R> pageResult = new MongoPageResult<>();pageResult.setTotal(total);pageResult.setPages(pages);pageResult.setPageSize(pageSize);pageResult.setPageNum(pageNum);pageResult.setList(entityList.stream().map(mapper).collect(Collectors.toList()));return pageResult;}}
package com.hh.framework.page;import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;/*** 分页结果.*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(Include.NON_NULL)
public class MongoPageResult<T> {@Schema(description = "页码,从1开始")private Integer pageNum;@Schema(description = "页面大小")private Integer pageSize;@Schema(description = "总数")private Long total;@Schema(description = "总页数")private Integer pages;@Schema(description = "数据")private List<T> list;}
package com.hh.framework.page;import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.util.List;/*** 分页结果.*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(Include.NON_NULL)
public class MongoPageResult<T> {@Schema(description = "页码,从1开始")private Integer pageNum;@Schema(description = "页面大小")private Integer pageSize;@Schema(description = "总数")private Long total;@Schema(description = "总页数")private Integer pages;@Schema(description = "数据")private List<T> list;}
6、业务模块使用:service层
@Autowired@Qualifier("primaryMongo")private MongoTemplate primaryMongoTemplate;@Overridepublic List getList() {Criteria criteria = Criteria.where("id").in().and("code").gte("").lte("");Query query = Query.query(criteria).with(Sort.by(Sort.Direction.DESC,"code"));return primaryMongoTemplate.find(query, CityEntity.class);}相关文章:
SpriingBoot整合MongoDB多数据源
背景: MongoDB多数据源:springboot为3以上版本,spring-boot-starter-data-mongodb低版本MongoDBFactory已过时, 改为MongoDatabaseFactory。 1、pom引入: <dependency><groupId>org.springframework.boo…...
深入浅出 -- 系统架构之负载均衡Nginx缓存机制
一、Nginx缓存机制 对于性能优化而言,缓存是一种能够大幅度提升性能的方案,因此几乎可以在各处都能看见缓存,如客户端缓存、代理缓存、服务器缓存等等,Nginx的缓存则属于代理缓存的一种。对于整个系统而言,加入缓存带来…...
前端 小程序框架UniApp
小程序框架UniApp uni-app简介uni-app项目结构uni-app开发工具HBuilderXuni-app页面uni-app页面生命周期uni-app组件生命周期uni-app页面调用接口uni-app页面通讯uni-app pages.json 页面路由uni-app组件viewuni-app组件scroll-viewuni-app组件swiperuni-app组件textuni-app组…...
宏集PLC如何为楼宇自动化行业提供空调、供暖与通风的解决方案?
一、应用背景 楼宇自动化行业是通过将先进的技术和系统应用于建筑物中,以提高其运营效率、舒适度和能源利用效率的行业,其目标是使建筑物能够自动监控、调节和控制各种设备和系统,包括照明系统、空调系统、安全系统、通风系统、电力供应系统…...
【TI毫米波雷达】官方工业雷达包的生命体征检测环境配置及避坑(Vital_Signs、IWR6843AOPEVM)
【TI毫米波雷达】官方工业雷达包的生命体征检测环境配置及避坑(Vital_Signs、IWR6843AOPEVM) 文章目录 生命体征基本介绍IWR6843AOPEVM的配置上位机配置文件避坑上位机start测试距离检测心跳检测呼吸频率检测空环境测试 附录:结构框架雷达基…...
计算机毕业设计选题之基于SSM的旅游管理系统【源码+PPT+文档+包运行成功+部署讲解】
💓项目咨询获取源码联系v💓xiaowan1860💓 🚩如何选题?🍑 对于项目设计中如何选题、让题目的难度在可控范围,以及如何在选题过程以及整个毕设过程中如何与老师沟通,有疑问不清晰的可…...
JavaWeb入门——Web前端概述及HTML,CSS语言基本使用
前言: java基础已经学完,开始学习javaWeb相关的内容,整理下笔记,打好基础,daydayup!!! Web Web:全球广域网,也称万维网(www World Wide Web),能够通过浏览器访…...
数据结构(3)----栈和队列
目录 一.栈 1.栈的基本概念 2.栈的基本操作 3.顺序栈的实现 •顺序栈的定义 •顺序栈的初始化 •进栈操作 •出栈操作 •读栈顶元素操作 •若使用另一种方式: 4.链栈的实现 •链栈的进栈操作 •链栈的出栈操作 •读栈顶元素 二.队列 1.队列的基本概念 2.队列的基…...
nestjs 全栈进阶--module
视频教程 10_模块Module1_哔哩哔哩_bilibili 1. 模块Module 在 Nest.js 中,Module 是框架的核心概念之一,用于组织和管理应用程序的不同部分,包括服务、控制器、中间件以及其他模块的导入。每个 Nest.js 应用程序至少有一个根模块…...
jupyter python paramiko 网络系统运维
概述 通过使用jupyter进行网络运维的相关测试 设备为H3C 联通性测试 import paramiko import time import getpass import re import os import datetimeusername "*****" password "*****" ip "10.32.**.**"ssh_client paramiko.SSHCli…...
Windows Edge浏览器兼容性问题诊断与修复策略详解
随着Microsoft Edge浏览器的持续迭代与更新,其性能与兼容性已得到了显著提升。然而,在面对互联网上纷繁复杂的网页内容时,仍有可能遇到兼容性问题。本文旨在探讨Edge浏览器在处理网页兼容性问题时的常见场景、原因分析及相应的解决方案&#…...
EXCEL学习笔记
EXCEL学习笔记 小技巧 一键批量添加后缀名词/单词 单元格格式-自定义-通用格式后面输入相应的单位,比如“元”。 输入10000个序号,先输入1,点击开始-填充-序列,选中该列,终止值为10000; 按住shift选取多个…...
使用预训练的bert large model实现问答系统源码(本地实现 question answer system)
pre-trained bert model 预训练好的Bert模型 本地实现问答系统 用这条命令将bert下载到本地: model.save_pretrained("path/to/model") 具体代码 如下链接: https://download.csdn.net/download/qqqweiweiqq/89092005...
蓝桥杯 历届真题 杨辉三角形【第十二届】【省赛】【C组】
资源限制 内存限制:256.0MB C/C时间限制:1.0s Java时间限制:3.0s Python时间限制:5.0s 思路: 由于我第一写没考虑到大数据的原因,直接判断导致只得了40分,下面是我的代码: #…...
商务电子邮件: 在WorkPlace中高效且安全
高效和安全的沟通是任何组织成功的核心。在我们关于电子邮件类型的系列文章的第二期中,我们将重点关注商业电子邮件在促进无缝交互中的关键作用。当你身处重要的工作场环境时,本系列的每篇文章都提供了电子邮件的不同维度的视角。 “2024年,全…...
阿里云2024年优惠券领取及使用常见问题
阿里云是阿里巴巴旗下云计算品牌,服务涵盖云服务器、云数据库、云存储、域名注册等全方位云服务和各行业解决方案。为了吸引用户上云,阿里云经常推出各种优惠活动,其中就包括阿里云优惠券。本文将对阿里云优惠券领取及使用常见问题进行解答&a…...
90天玩转Python—05—基础知识篇:Python基础知识扫盲,使用方法与注意事项
90天玩转Python系列文章目录 90天玩转Python—01—基础知识篇:C站最全Python标准库总结 90天玩转Python--02--基础知识篇:初识Python与PyCharm 90天玩转Python—03—基础知识篇:Python和PyCharm(语言特点、学习方法、工具安装) 90天玩转Python—04—基础知识篇:Pytho…...
常见的常见免费开源绘图工具对比 draw.io/Excalidraw/Lucidchart/yEd Graph Editor/Dia/
拓展阅读 常见免费开源绘图工具 OmniGraffle 创建精确、美观图形的工具 UML-架构图入门介绍 starUML UML 绘制工具 starUML 入门介绍 PlantUML 是绘制 uml 的一个开源项目 UML 等常见图绘制工具 绘图工具 draw.io / diagrams.net 免费在线图表编辑器 绘图工具 excalidr…...
项目:自主实现Boost搜索引擎
文章目录 写在前面开源仓库和项目上线其他文档说明 项目背景项目的宏观原理技术栈与环境搜索引擎原理正排索引倒排索引 去标签和数据清洗模块html文件名路径保存函数html数据解析函数文件写入函数 建立索引模块检索和读取信息建立索引建立正排索引建立倒排索引jieba工具的使用倒…...
麒麟系统ARM安装rabbitmq
简单记录下,信创服务器:麒麟系统,安装rabbitmq的踩坑记录。 本文章参考了很多大佬文章,我整理后提供。 一、安装基础依赖 yum -y install make gcc gcc-c kernel-devel m4 ncurses-devel openssl-devel unixODBC-devel 二、下载…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...
大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
