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 二、下载…...

微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...

MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)
在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马(服务器方面的)的原理,连接,以及各种木马及连接工具的分享 文件木马:https://w…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...