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

手把手教你如何扩展(破解)mybatisplus的sql生成 | 京东云技术团队

mybatisplus 的常用CRUD方法

众所周知,mybatisplus提供了强大的代码生成能力,他默认生成的常用的CRUD方法(例如插入、更新、删除、查询等)的定义,能够帮助我们节省很多体力劳动。

他的BaseMapper中定义了这些常用的CRUD方法,我们在使用时,继承这个BaseMapper类就默认拥有了这些能力。

BaseMapper.png

如果我们的业务中,需要类似的通用Sql时,该如何实现呢?

是每个Mapper中都定义一遍类似的Sql吗?

显然这是最笨的一种方法。

此时我们可以借助mybatisplus这个成熟框架,来实现我们想要的通用Sql。

扩展常用CRUD方法

新增一个通用sql

比如有一个这样的需求,项目中所有表或某一些表,都要执行一个类似的查询,如`SelectByErp`,那么可以这样实现。(这是一个最简单的sql实现,使用时可以根据业务需求实现更为复杂的sql:比如多租户系统自动增加租户id参数、分库分表系统增加分库分表字段条件判断)

  1. 定义一个SelectByErp类,继承AbstractMethod类,并实现injectMappedStatement方法

  2. 定义sql方法名、sql模板、实现sql的拼接组装

/*** 新增一个通用sql*/
public class SelectByErp extends AbstractMethod {// 需要查询的列名private final String erpColumn = "erp";// sql方法名private final String method = "selectByErp";// sql模板private final String sqlTemplate = "SELECT %s FROM %s WHERE %s=#{%s} %s";@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {// 获取需要查询的字段名及属性名TableFieldInfo erpFiled = getErpProperty(tableInfo);// 拼接组装sqlSqlSource sqlSource = new RawSqlSource(configuration, String.format(sqlTemplate,sqlSelectColumns(tableInfo, false),tableInfo.getTableName(), erpFiled.getColumn(), erpFiled.getProperty(),tableInfo.getLogicDeleteSql(true, false)), Object.class);return this.addSelectMappedStatementForTable(mapperClass, method, sqlSource, tableInfo);
}/*** 查询erp列信息*/private TableFieldInfo getErpProperty(TableInfo tableInfo) {List<TableFieldInfo> fieldList = tableInfo.getFieldList();TableFieldInfo erpField = fieldList.stream().filter(filed -> filed.getColumn().equals(erpColumn)).findFirst().get();return erpField;}

3.定义一个sql注入器GyhSqlInjector,添加SelectByErp对象

// 需注入到spring容器中
@Component
public class GyhSqlInjector extends DefaultSqlInjector {    @Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass) {List<AbstractMethod> methodList = super.getMethodList(mapperClass);// 增加 SelectByErp对象,程序启动后自动加载methodList.add(new SelectByErp());return methodList;}
}

4.定义一个基础MapperGyhBaseMapper,添加selectByErp方法

/*** 自定义的通用Mapper*/
public interface GyhBaseMapper<T> extends BaseMapper<T> {List<T> selectByErp(String erp);
}

5.应用中需要使用该SelectByErp方法的表,都继承GyhBaseMapper,那么这些表将都拥有了selectByErp这个查询方法,程序启动后会自动为这些表生成该sql。

public interface XXXMapper extends GyhBaseMapper<XXXTable> 

添加一个mybatisplus已有sql

1.mybatisplus 常用CRUD方法如最上图,这些方法已经默认会自动生成,但mybatisplus其实提供了更多的方法,如下图,只要我们在启动时添加进去,就可以使用了。

method.png

2.比如我想使用AlwaysUpdateSomeColumnById方法,该方法可以在更新时只更新我需要的字段,不进行全字段更新。添加步骤如下。

3.定义一个sql注入器 ,如GyhSqlInjector,添加AlwaysUpdateSomeColumnById对象

@Component
public class GyhSqlInjector extends DefaultSqlInjector {    @Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass) {List<AbstractMethod> methodList = super.getMethodList(mapperClass);// 添加 AlwaysUpdateSomeColumnById 对象methodList.add(new AlwaysUpdateSomeColumnById());return methodList;}
}

4.定义一个基础Mapper 如GyhBaseMapper,添加alwaysUpdateSomeColumnById方法

/*** 自定义的通用Mapper*/
public interface GyhBaseMapper<T> extends BaseMapper<T> {int alwaysUpdateSomeColumnById(@Param(Constants.ENTITY) T entity);
}

5.继承GyhBaseMapper的其他Mapper,将自动拥有alwaysUpdateSomeColumnById方法

/*** 自定义的通用Mapper*/
public interface GyhBaseMapper<T> extends BaseMapper<T> {int alwaysUpdateSomeColumnById(@Param(Constants.ENTITY) T entity);
}

6.继承GyhBaseMapper的其他Mapper,将自动拥有alwaysUpdateSomeColumnById方法

编辑一个mybatisplus已有sql

1.如果想编辑一个mybatisplus已有sql,比如分库分表系统,执行updateById操作时,虽然主键Id已确定,但目标表不确定,此时可能导致该sql在多张表上执行,造成资源浪费,并且分库分表字段不可修改,默认的updateById不能用,需要改造。以下以shardingsphere分库分表为例。

2.定义一个UpdateByIdWithSharding类,继承UpdateById

public class UpdateByIdWithSharding extends UpdateById {private String columnDot = "`";private YamlShardingRuleConfiguration yamlShardingRuleConfiguration;// 注入shardingsphere的分库分表配置信息public UpdateByIdWithSharding(YamlShardingRuleConfiguration yamlShardingRuleConfiguration) {this.yamlShardingRuleConfiguration = yamlShardingRuleConfiguration;}@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {String tableName = tableInfo.getTableName();// shardingsphere 分库分表配置信息Map<String, YamlTableRuleConfiguration> tables = yamlShardingRuleConfiguration.getTables();// 判断当前表是否设置了分表字段if (tables.containsKey(tableName)) {YamlTableRuleConfiguration tableRuleConfiguration = tables.get(tableName);// 获取分表字段String shardingColumn = tableRuleConfiguration.getTableStrategy().getStandard().getShardingColumn();// 构建sqlboolean logicDelete = tableInfo.isLogicDelete();SqlMethod sqlMethod = SqlMethod.UPDATE_BY_ID;// 增加分表字段判断String shardingAdditional = getShardingColumnWhere(tableInfo, shardingColumn);// 是否判断逻辑删除字段final String additional = optlockVersion() + tableInfo.getLogicDeleteSql(true, false);shardingAdditional = shardingAdditional + additional;String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(),getSqlSet(logicDelete, tableInfo, shardingColumn),tableInfo.getKeyColumn(), ENTITY_DOT + tableInfo.getKeyProperty(),shardingAdditional);SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);return addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);} else {return super.injectMappedStatement(mapperClass, modelClass, tableInfo);}}/*** where条件增加分表字段*/private String getShardingColumnWhere(TableInfo tableInfo, String shardingColumn) {StringBuilder shardingWhere = new StringBuilder();shardingWhere.append(" AND ").append(shardingColumn).append("=#{");shardingWhere.append(ENTITY_DOT);TableFieldInfo fieldInfo = tableInfo.getFieldList().stream().filter(f -> f.getColumn().replaceAll(columnDot, StringUtils.EMPTY).equals(shardingColumn)).findFirst().get();shardingWhere.append(fieldInfo.getEl());shardingWhere.append("}");return shardingWhere.toString();}/*** set模块去掉分表字段*/public String getSqlSet(boolean ignoreLogicDelFiled, TableInfo tableInfo, String shardingColumn) {List<TableFieldInfo> fieldList = tableInfo.getFieldList();// 去掉分表字段的set设置,即不修改分表字段String rmShardingColumnSet = fieldList.stream().filter(i -> ignoreLogicDelFiled ? !(tableInfo.isLogicDelete() && i.isLogicDelete()) : true).filter(i -> !i.getColumn().equals(shardingColumn)).map(i -> i.getSqlSet(ENTITY_DOT)).filter(Objects::nonNull).collect(joining(NEWLINE));return rmShardingColumnSet;}
}

3.定义一个sql注入器GyhSqlInjector,添加UpdateByIdWithSharding对象

// 需注入到spring容器中
@Component
public class GyhSqlInjector extends DefaultSqlInjector {    /*** shardingsphere 配置信息*/@Autowiredprivate YamlShardingRuleConfiguration yamlShardingRuleConfiguration;@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass) {List<AbstractMethod> methodList = super.getMethodList(mapperClass);// 添加 UpdateByIdWithSharding 对象,并注入分库分表信息methodList.add(new UpdateByIdWithSharding(yamlShardingRuleConfiguration));return methodList;}
}

4.定义一个基础MapperGyhBaseMapper,添加新的selectById方法

/*** 自定义的通用Mapper*/
public interface GyhBaseMapper<T> extends BaseMapper<T> {int updateById(@Param(Constants.ENTITY) T entity);
}

5.所有参与分表的表,在定义Mapper时继承GyhBaseMapper,那么在使用他的updateById方法时,将自动增加分库分表判断,准确命中目标表,减少其他分表查询的资源浪费。


以上是针对mybatisplus的一些简单改造,希望能为你提供一点点帮助~

作者:京东科技 郭艳红

来源:京东云开发者社区 转载请注明来源

相关文章:

手把手教你如何扩展(破解)mybatisplus的sql生成 | 京东云技术团队

mybatisplus 的常用CRUD方法 众所周知&#xff0c;mybatisplus提供了强大的代码生成能力&#xff0c;他默认生成的常用的CRUD方法&#xff08;例如插入、更新、删除、查询等&#xff09;的定义&#xff0c;能够帮助我们节省很多体力劳动。 他的BaseMapper中定义了这些常用的C…...

Spring Data JPA 项目配置与QueryDSL集成

一、说明 Spring Data JPA通过Spring Initializer创建时勾选相关依赖即可引入&#xff0c;QueryDSL需要单独引入。Spring JPA针对QueryDSL有比较好的兼容性&#xff0c;可以实现优雅的SQL构建。 二、设置JPA默认配置&#xff08;yaml格式&#xff09; spring:jpa:hibernate:…...

UE5数字孪生制作-数据篇(二) - 数据处理

1.卫星图与DEM高度图坐标一致处理 https://www.bilibili.com/video/BV1op4y1V71r?p4&vd_source707ec8983cc32e6e065d5496a7f79ee6 坐标系的调整 如何使用临时图层&#xff0c;对其他数据层进行裁切 &#xff08;1&#xff09;创建临时图层 &#xff08;2&#xff09;在临…...

Java 设计模式——享元模式

目录 1.概述2.结构3.实现3.1.抽象享元3.2.具体享元3.3.享元工厂3.4.测试 4.优缺点5.使用场景6.JDK 源码解析——Integer 类 1.概述 &#xff08;1&#xff09;享元模式 (Flyweight Pattern) 是一种结构型设计模式&#xff0c;主要通过共享对象来减少系统中的对象数量&#xff…...

再扩国产化适配版图,长安链新增数据库兼容性认证

基础软件的自主可控影响着国家信息安全与产业技术发展是否受制于人。实现真正长期可持续的技术自主可控&#xff0c;需要再进一步的是让国产化信息系统生态更有”活性“&#xff0c;基础软件之间、基础软件与其他国产上层应用的互相兼容、互相促进&#xff0c;共同繁荣发展&…...

MES系统数据集成系统源码

MES系统数据集成系统源码 1 MES的生产计划管理综述 生产计划的管理在MES系统中是非常重要的。我们知道&#xff0c;一般的情况下&#xff0c;企业的生产计划是由上层管理系统ERP来完成&#xff0c;那么MES中的生产计划和ERP的生产计划的不同点在于&#xff1a; ERP的生产计划…...

关于道一云-七巧使用感悟

低代码&#xff0c;开发快速&#xff0c;缺点组件比较少但能满足大多数场景&#xff0c;如果需要的话得自己造&#xff0c;官方的技术群里面普遍问题响应就很快&#xff0c;技术文档这个会抽风&#xff0c;有些代码就改个筛选条件本地死活运行不了&#xff0c;去官网那里问他们…...

去中心化数据云项目Oort主网即将上线

备受期待的去中心化数据云项目Oort&#xff0c;今日已通过官方X账号官宣&#xff0c;将于纽约时间11月27日正式上线主网Olympus Protocol。届时&#xff0c;用户也能够通过Oort的Ale Wallet钱包和开发者API使用主网&#xff0c;并可通过OORT浏览器查询交易和合约&#xff0c;开…...

CSS知识点梳理(一)

CSS 是层叠样式表&#xff08;Cascading Style Sheets&#xff09;的缩写&#xff0c;它是一种用于描述 HTML 或 XML&#xff08;包括如 SVG、MathML 等派生语言&#xff09;文档呈现的语言。CSS 可以用来控制文档的布局、颜色、字体等外观属性。 CSS 的主要特点包括&#xff…...

网络安全深入学习第八课——反向代理(工具:frp)

文章目录 一、实验环境二、实验要求三、开始模拟1、攻击机配置frp文件2、攻击拿下跳板机&#xff0c;并且上传frpc.ini、frpc.exe、frpc_full.ini文件3、把frps.ini、、frps.exe、frps_full.ini文件放到VPS主机上4、VPS机开启frp5、跳板机开启frp6、验证 一、实验环境 攻击机&…...

浅谈前端自定义VectorGrid矢量瓦片样式

目录 前言 一、VectorGrid相关API介绍 1、VectorGrid 2、 LayerStyles样式详解 二、样式自动配置 1、页面定义 2、地图及PBF瓦片引入 3、矢量瓦片样式定义 4、鼠标事件交互 三、最终效果 1、自定义样式展示 2、鼠标交互 总结 前言 在上一篇博客中&#xff0c;详细讲…...

Qt5多线程<12>

1.多线程的简单实现 <1> 在头文件threaddlg.h声明用于界面显示所需的控件,其代码如下: #ifndef THREADDLG_H #define THREADDLG_H#include <QDialog> #include <QPushButton> #include "workthread.h" #define MAXSIZE 5class ThreadDlg : publ…...

Linux学习笔记之五(父子进程、孤儿进程、僵尸进程、守护进程)

Linux 1、进程1.1、进程的六种状态1.2、创建子进程1.3、添加子进程任务1.4、孤儿进程、僵尸进程、守护进程1.4.1、避免僵尸进程1.4.2、创建守护进程1.4.3、杀死守护进程 1.5、综合练习 1、进程 进程可以简单的理解为一个正在执行的程序&#xff0c;它是计算机系统中拥有资源和…...

[题] 不容易系列之(3)―― LELE的RPG难题 #DP

题目 不容易系列之(3)―― LELE的RPG难题 思路 简单的DP题。 代码 #include<bits/stdc.h> using namespace std; //默认以0开头&#xff0c;以1和2结尾。f[i][1]表示长度为i的以1结尾的涂抹方案 //状态转移方程&#xff1a;若以1结尾&#xff0c;则前面一个格子只能是…...

pip 安装任意软件包报错

现象 使用 pip 命令时提示 查看源码 可以看到是从 pip 包中导入 main失败&#xff0c;点击查看目录 main 文件不见了&#xff0c;判断是文件缺失&#xff0c;重装 pip 即可 # python3 下载 pip curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py # python2 下载…...

NLP之Bert实现文本多分类

文章目录 代码代码整体流程解读debug上面的代码 代码 from pypro.chapters03.demo03_数据获取与处理 import train_list, label_list, val_train_list, val_label_list import tensorflow as tf from transformers import TFBertForSequenceClassificationbert_model "b…...

对话大众软件子公司:中国的智舱、智驾比欧洲早一代

作者 | 德新 编辑 | 王博 尤其在上海车展之后&#xff0c;大部分的外资车企都在转型调整。 2023年的上海车展是一个重要节点。在这之前&#xff0c;疫情阻断了国内和海外频繁的线下交流&#xff0c;而国内汽车的新能源化和智能化在这期间完成了一次飞跃式的发展。所以车展开…...

基于FPGA的图像RGB转HSV实现,包含testbench和MATLAB辅助验证程序

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1. RGB与HSV色彩空间 4.2. RGB到HSV转换原理 5.算法完整程序工程 1.算法运行效果图预览 将FPGA的仿真结果导入到matlab中&#xff1a; 2.算法运行软件版本 vivado2019.2 matlab2022a …...

小型企业如何数字化转型?ZohoCRM助力小企业转型

小型企业数字化之路倍加艰难&#xff0c;其组织规模有限、资源有限&#xff0c;数字化布局或转型&#xff0c;也存在与数字平台匹配度的问题。其实小型企业可以通过CRM客户管理系统实现高效的客户关系管理&#xff0c;进一步提高市场竞争力。 建立高效易用的客户关系管理系统 …...

聊聊模板引擎<Template engine>

模板引擎是什么 模板引擎是一种用于生成动态内容的工具&#xff0c;通常用于Web开发中。它能够将静态的模板文件和动态数据结合起来&#xff0c;生成最终的HTML、XML或其他文档类型。模板引擎通过向模板文件中插入变量、条件语句、循环结构等控制语句&#xff0c;从而实现根据…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】&#xff0c;注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录&#xff08;即exe所在文件夹&#xff09;加入系统变量…...

day36-多路IO复用

一、基本概念 &#xff08;服务器多客户端模型&#xff09; 定义&#xff1a;单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用&#xff1a;应用程序通常需要处理来自多条事件流中的事件&#xff0c;比如我现在用的电脑&#xff0c;需要同时处理键盘鼠标…...

毫米波雷达基础理论(3D+4D)

3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文&#xff1a; 一文入门汽车毫米波雷达基本原理 &#xff1a;https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...

消息队列系统设计与实践全解析

文章目录 &#x1f680; 消息队列系统设计与实践全解析&#x1f50d; 一、消息队列选型1.1 业务场景匹配矩阵1.2 吞吐量/延迟/可靠性权衡&#x1f4a1; 权衡决策框架 1.3 运维复杂度评估&#x1f527; 运维成本降低策略 &#x1f3d7;️ 二、典型架构设计2.1 分布式事务最终一致…...

从零开始了解数据采集(二十八)——制造业数字孪生

近年来&#xff0c;我国的工业领域正经历一场前所未有的数字化变革&#xff0c;从“双碳目标”到工业互联网平台的推广&#xff0c;国家政策和市场需求共同推动了制造业的升级。在这场变革中&#xff0c;数字孪生技术成为备受关注的关键工具&#xff0c;它不仅让企业“看见”设…...

如何把工业通信协议转换成http websocket

1.现状 工业通信协议多数工作在边缘设备上&#xff0c;比如&#xff1a;PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发&#xff0c;当设备上用的是modbus从站时&#xff0c;采集设备数据需要开发modbus主站&#xff1b;当设备上用的是西门子PN协议时&#xf…...

Tauri2学习笔记

教程地址&#xff1a;https://www.bilibili.com/video/BV1Ca411N7mF?spm_id_from333.788.player.switch&vd_source707ec8983cc32e6e065d5496a7f79ee6 官方指引&#xff1a;https://tauri.app/zh-cn/start/ 目前Tauri2的教程视频不多&#xff0c;我按照Tauri1的教程来学习&…...