当前位置: 首页 > news >正文

MyBatis-Plus如何优雅的配置多租户及分页

MyBatis-Plus如何优雅的配置多租户及分页

  • 一、配置多租户
    • 1、步骤一
    • 2、步骤二
    • 3、步骤三
    • 步骤四
  • 二、配置分页
    • 1、步骤一
    • 2、步骤二
    • 3、步骤三

一、配置多租户

TenantLineInnerInterceptorMyBatis-Plus 提供的一个插件,用于实现多租户的数据隔离。通过这个插件,可以确保每个租户只能访问自己的数据,从而实现数据的安全隔离。

1、步骤一

通过实现 TenantLineHandler 接口,处理租户相关的逻辑:

import com.baomidou.mybatisplus.core.parser.ISqlParser;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.tenant.TenantHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.springframework.stereotype.Component;import javax.servlet.http.HttpServletRequest;
import java.util.List;@Component
public class CustomTenantHandler implements TenantHandler {@Overridepublic Expression getTenantId() {// 假设有一个租户上下文,能够从中获取当前用户的租户Long tenantId = TenantContextHolder.getCurrentTenantId();// 返回租户ID的表达式return tenantId;}@Overridepublic String getTenantIdColumn() {return "tenant_id";}@Overridepublic boolean ignoreTable(String tableName) {// 根据需要返回是否忽略该表return false;}@Overridepublic void setProperties(Properties properties) {// 可以设置一些属性}
}

2、步骤二

但在实际应用场景中会存在部分表不分租户,这时需要忽略租户过滤指定表,常规情况下我们可能会定义一个常量数据来判断,但这样不方便维护,可以通过反射判断当前表是否存在租户id字段,以此忽略租户隔离:

/*** <p>* 租户处理器* </p>** @author 瞄你个汪* @since 2024/6/2 16:15*/
@Slf4j
@Component
public class TableTenantLineHandler implements TenantLineHandler {@Autowiredprivate AppConfiguration appConfig;...@Overridepublic boolean ignoreTable(String tableName) {return Strings.isEmpty(tableName) || appConfig.notHasTenantColumn(tableName, getTenantIdColumn());}...
}

3、步骤三

判断表是否存在租户字段:


/*** <p>*  应用配置类* </p>* @author 瞄你个汪* @since 2024/5/29 12:55*/
@Data
@Component
public class AppConfiguration {...// 这里我使用了SpringBoot Cache缓存@Cacheable(value="system", key="#methodName + ':' + #tableName")public boolean notHasTenantColumn(String tableName, String tenantId) {// TableInfoHelper 为MyBatis-Plus中的工具类List<TableInfo> tableInfos = TableInfoHelper.getTableInfos();for (TableInfo table : tableInfos) {if (tableName.equals(table.getTableName())) {return table.getFieldList().stream().noneMatch(x -> tenantId.equals(x.getColumn()));}}return false;}
}

步骤四

注入租户处理器

/*** <p>* MybatisPlus 配置* </p>* @author 瞄你个汪* @since 2024/6/2 16:30*/
@Configuration
@MapperScan("top.xxxx.mapper")
public class MybatisPlusConfig {@Autowiredprivate TableTenantLineHandler tableTenantLineHandler;@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();TenantLineInnerInterceptor tenantInterceptor = new TenantLineInnerInterceptor();tenantInterceptor.setTenantLineHandler(tableTenantLineHandler);interceptor.addInnerInterceptor(tenantInterceptor);return interceptor;}
}

二、配置分页

1、步骤一

编写通用分页查询接口输入参数类:

/*** <p>* Http 分页查询输入参数* </p>* @author 瞄你个汪* @since 2024-05-01 12:00:00*/
@Data
public class PageInput<S> {/*** 查询条件*/private S search;/*** 页容量*/@Min(value = 1, message = "页容量不能小于1")private long size = 10;/*** 当前页*/@Min(value = 1, message = "当前页不能小于1")private long page = 1;/*** 排序字段*/private List<OrderItem> orders;public <R> IPage<R> getPage() {Page<R> page = new Page<>(this.page, size);page.setOrders(orders);page.setMaxLimit(500L);return page;}/*** 传递分页参数并设置查询记录*/public <R> IPage<R> reader(Function<IPage<R>, List<R>> func) {IPage<R> page = getPage();return page.setRecords(func.apply(page));}/*** 传递分页参数并设置查询记录*/public <R> IPage<R> reader(BiFunction<IPage<R>, QueryWrapper<R>, List<R>> func) {IPage<R> page = getPage();return page.setRecords(func.apply(page, new QueryWrapper<>()));}
}

2、步骤二

注入分页插件:

/*** <p>* MybatisPlus 配置* </p>* @author 瞄你个汪* @since 2024/6/2 16:30*/
@Configuration
@MapperScan("top.xxxx.mapper")
public class MybatisPlusConfig {@Autowiredprivate TableTenantLineHandler tableTenantLineHandler;@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();...// 分页配置, 这行配置必须放最后interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}

3、步骤三

使用:

/*** <p>* 系统用户表 前端控制器* </p>* @author 瞄你个汪* @since 2024-01-01 12:00:00*/
@Api(tags = "⚙ 系统用户管理")
@RestController()
@RequestMapping("/api/sysUser")
public class SysUserController {private final ISysUserService service;@Autowiredpublic SysUserController(SysUserServiceImpl _service) {service = _service;}/*** <p>*  分页查询系统用户数据* </p>* @param page 分页参数* @return 查询结果*/@PostMapping("page")@ApiOperation(value = "分页查询", notes = "分页查询系统用户数据")public Result<IPage<SysUser>> queryByPage(@Validated @RequestBody PageInput<String> page) {String search = page.getSearch();boolean notEmpty = Strings.isNotEmpty(search);return Result.ok(page.reader((fPage, query) -> {query.lambda().like(notEmpty, SysUser::getMobile, search).like(notEmpty, SysUser::getAccount, search).like(notEmpty, SysUser::getRealName, search).like(notEmpty, SysUser::getNickName, search);return this.service.list(fPage, query);}));}...
}

没有过滤条件:

	@PostMapping("page")@ApiOperation(value = "分页查询", notes = "分页查询系统用户数据")public Result<IPage<SysUser>> queryByPage(@Validated @RequestBody PageInput<String> page) {return Result.ok(page.reader((_page, query) -> this.service.list(_page, query)));}

PS:觉得可以请帮忙点赞收藏,万分感谢🫡🫡🫡

相关文章:

MyBatis-Plus如何优雅的配置多租户及分页

MyBatis-Plus如何优雅的配置多租户及分页 一、配置多租户1、步骤一2、步骤二3、步骤三步骤四 二、配置分页1、步骤一2、步骤二3、步骤三 一、配置多租户 TenantLineInnerInterceptor 是 MyBatis-Plus 提供的一个插件&#xff0c;用于实现多租户的数据隔离。通过这个插件&#…...

国产操作系统上Vim的详解01--vim基础篇 _ 统信 _ 麒麟 _ 中科方德

原文链接&#xff1a;国产操作系统上Vim的详解01–vim基础篇 | 统信 | 麒麟 | 中科方德 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇在国产操作系统上使用Vim的详解文章。Vim是一款功能强大且高度可定制的文本编辑器&#xff0c;广泛应用于编程和日常文本编辑中。…...

如何正确理解事件溯源架构模式?

在微服务架构盛行的当下&#xff0c;DDD&#xff08;领域驱动设计&#xff09;也得到了崭新的发展。同时&#xff0c;随着DDD的不断发展&#xff0c;也诞生了一些新的设计思想和开发模式&#xff0c;今天要介绍的事件溯源是其中具有代表性的一种模式。 事件溯源模式是DDD领域中…...

【漏洞复现】电信网关配置管理系统 rewrite.php 文件上传漏洞

0x01 产品简介 中国电信集团有限公司(英文名称"China Telecom”、简称“"中国电信”)成立于2000年9月&#xff0c;是中国特大型国有通信企业、上海世博会全球合作伙伴。电信网关配置管理系统是一个用于管理和配置电信网络中网关设备的软件系统。它可以帮助网络管理员…...

线性调整率:LINE REGULATION详解

目录 一、概述 二、 举例 一、概述 LDO&#xff08;低压差线性稳压器&#xff09;的LINE REGULATION&#xff08;线路调整或线性调整&#xff09;参数是一个衡量稳压器输出稳定性的重要指标。它反映了LDO输出电压对输入电压变化的响应程度。 当输入电压在其规定的工作范围内变…...

Workfine默认首页功能详解

一、基本介绍 Workfine V6.3推出了默认的用户首页功能&#xff0c;这样用户在登入系统后就可以通过默认的首页栏进行一些业务操作。第一版的用户首页功能布局了审批&#xff0c;制单&#xff0c;业务导航&#xff0c;便捷入口&#xff0c;消息和预警六大块内容&#xff0c;后续…...

CSAPP Lab07——Malloc Lab完成思路

等不到天黑 烟火不会太完美 回忆烧成灰 还是等不到结尾 ——她说 完整代码见&#xff1a;CSAPP/malloclab-handout at main SnowLegend-star/CSAPP (github.com) Malloc Lab 按照惯例&#xff0c;我先是上来就把mm.c编译了一番&#xff0c;结果产生如下报错。搜索过后看样子应…...

简单、免费、无广告的高性能多线程文件下载工具

一、简介 1、它是一款免费、无广告的高性能多线程文件下载工具。它界面简洁&#xff0c;简单好用&#xff0c;压缩包大小仅有 0.7MB&#xff0c;目前仅支持 Windows 平台。 2、使用方法&#xff1a;点击程序左上角的【】按钮&#xff0c;将需要的链接输入进去后点击【下载】即…...

【退役之重学 SQL】什么是笛卡尔积

一、初识笛卡尔积 概念&#xff1a; 笛卡尔积是指在关系型数据库中&#xff0c;两个表进行 join 操作时&#xff0c;没有指定任何条件&#xff0c;导致生成的结果集&#xff0c;是两个表中所有行的组合。 简单来说&#xff1a; 笛卡尔积是两个表的乘积&#xff0c;结果集中的每…...

Vue3禁止 H5 界面放大与缩小功能

Vue3禁止 H5 界面放大与缩小功能 一、前言1.第一步2.第二部3.总结 一、前言 当涉及到禁止 H5 界面的放大与缩小功能时&#xff0c;Vue 3 提供了一种方便的方式来处理。我们可以使用 <script setup> 语法&#xff0c;将相关代码添加到 App.vue 组件中&#xff0c;以确保在…...

上位机图像处理和嵌入式模块部署(f407 mcu中tf卡读写和fatfs挂载)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 很早之前&#xff0c;个人对tf卡并不是很重视&#xff0c;觉得它就是一个存储工具而已。后来在移植v3s芯片的时候&#xff0c;才发现很多的soc其实…...

汽车识别项目

窗口设计 这里的代码放在py文件最前面或者最后面都无所谓 # 创建主窗口 window tk.Tk() window.title("图像目标检测系统") window.geometry(1000x650) # 设置窗口大小# 创建背景画布并使用grid布局管理器 canvas_background tk.Canvas(window, width1000, height…...

【面试题-012】什么是Spring 它有哪些优势

文章目录 Spring有哪些优势有哪些优势Spring和Springboot区别在 Spring 框架中&#xff0c;什么是AOP核心概念应用场景 Spring有哪些通知类型 Spring 是一个开源的 Java 平台&#xff0c;由 Rod Johnson 创建&#xff0c;用于简化企业级 Java 应用程序的开发。它于 2003 年首次…...

ImageButton src图片会照成内存泄露吗 会使native内存增加吗?

在Android开发中&#xff0c;ImageButton 是用来显示按钮的视图组件&#xff0c;它通常用于显示图标或图片。对于ImageButton使用的src属性&#xff08;即按钮上的图片&#xff09;通常不会导致内存泄漏&#xff0c;但是有几种情况可能会导致内存问题&#xff1a; 1. **不正确…...

负载均衡与容错性:集群模式在分布式系统中的应用

本文作者:小米,一个热爱技术分享的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号“软件求生”,获取更多技术干货! 大家好,我是小米,一个热爱分享技术的29岁程序员。今天我们来聊一聊分布式系统中的一个重要概念:集群(Cluster)模式。相信很多朋友在日常开发…...

【UE5.1 角色练习】09-物体抬升、抛出技能 - part1

前言 在上一篇&#xff08;【UE5.1 角色练习】08-传送技能&#xff09;的基础上继续实现控制物体抬升、抛出的功能。 效果 步骤 一、准备技能动画 1. 在项目设置中新建一个操作映射&#xff0c;这里命名为“Skill_GravityControl”&#xff0c;用按键4触发 2. 通过IK重定向…...

最大的游戏交流社区Steam服务器意外宕机 玩家服务受影响

易采游戏网6月3日消息&#xff1a;众多Steam游戏玩家报告称&#xff0c;他们无法访问Steam平台上的个人资料、好友列表和社区市场等服务。同时&#xff0c;社区的讨论功能也无法正常使用。经过第三方网站SteamDB的确认&#xff0c;&#xff0c;这一现象是由于Steam社区服务器突…...

如何手动批准内核扩展 Tuxera NTFS for mac内核扩展需要批准 内核扩展怎么打开

在了解如何手动批准内核扩展之前&#xff0c;我们应该先了解什么叫做内核扩展。内核扩展又被称为KEXT&#xff0c;通过它可以实现macOS系统与软件组件之间的交互&#xff0c;例如磁盘管理、任务管理和内存管理等等。 kext 是内核扩展&#xff08;Kernel Extension&#xff09;…...

ffmpeg常用命令

推流 ffmpeg -re -stream_loop -1 -i in.flv -c copy -f flv outurl 推流追加时间戳 ffmpeg -stream_loop -1 -re -i move.flv -vf "settbAVTB,setptstrunc(PTS/1K)*1Kst(1,trunc(RTCTIME/1K))-1K*trunc(ld(1)/1K),drawtextfontfilearial.ttf:text%{localtime}.%{eif\:…...

在MongoDB中,您可以通过以下步骤来创建账号密码,并限制其在特定数据库上的访问权限

在MongoDB中&#xff0c;您可以通过以下步骤来创建账号密码&#xff0c;并限制其在特定数据库上的访问权限&#xff1a; 连接到MongoDB数据库&#xff1a; 使用MongoDB的客户端&#xff08;如mongo shell或者MongoDB Compass&#xff09;连接到MongoDB服务器。 切换到admin数…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

第25节 Node.js 断言测试

Node.js的assert模块主要用于编写程序的单元测试时使用&#xff0c;通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试&#xff0c;通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域&#xff0c;MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步&#xff0c;这两种通讯协议也正在被逐步融合&#xff0c;形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...