Mybatis-plus进阶篇-八

一.持久层接口补充

1.Mapper 层选装件

选装件是 Mybatis-Plus 提供的一些扩展方法,它们位于 com.baomidou.mybatisplus.extension.injector.methods 包下。这些方法需要配合Sql 注入器使用,以扩展 Mapper 接口的功能。

使用这些选装件前,需要确保已经正确配置了 Sql 注入器。

选装件说明

1>alwaysUpdateSomeColumnById
int alwaysUpdateSomeColumnById(T entity);
源码:
package com.baomidou.mybatisplus.extension.injector.methods;import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;import java.util.function.Predicate;/*** 根据 ID 更新固定的那几个字段(但是不包含逻辑删除)** <p>* 自己的通用 mapper 如下使用:* <pre>* int alwaysUpdateSomeColumnById(@Param(Constants.ENTITY) T entity);* </pre>* </p>** <p> 如何筛选字段参考请 {@link InsertBatchSomeColumn} 里面的注释 </p>** @author hubin* @since 2019-04-12*/
public class AlwaysUpdateSomeColumnById extends AbstractMethod {/*** 字段筛选条件*/@Setter@Accessors(chain = true)private Predicate<TableFieldInfo> predicate;/*** @param name      方法名* @param predicate 筛选条件* @since 3.5.0*/public AlwaysUpdateSomeColumnById(String name, Predicate<TableFieldInfo> predicate) {super(name);this.predicate = predicate;}public AlwaysUpdateSomeColumnById() {super("alwaysUpdateSomeColumnById");}/*** @param predicate 筛选条件*/public AlwaysUpdateSomeColumnById(Predicate<TableFieldInfo> predicate) {super("alwaysUpdateSomeColumnById");this.predicate = predicate;}@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {SqlMethod sqlMethod = SqlMethod.UPDATE_BY_ID;final String additional = optlockVersion(tableInfo) + tableInfo.getLogicDeleteSql(true, true);String sqlSet = this.filterTableFieldInfo(tableInfo.getFieldList(), getPredicate(),i -> i.getSqlSet(true, ENTITY_DOT), NEWLINE);sqlSet = SqlScriptUtils.convertSet(sqlSet);String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlSet,tableInfo.getKeyColumn(), ENTITY_DOT + tableInfo.getKeyProperty(), additional);SqlSource sqlSource = super.createSqlSource(configuration, sql, modelClass);return addUpdateMappedStatement(mapperClass, modelClass, methodName, sqlSource);}private Predicate<TableFieldInfo> getPredicate() {Predicate<TableFieldInfo> noLogic = t -> !t.isLogicDelete();if (predicate != null) {return noLogic.and(predicate);}return noLogic;}}
功能:

这个方法用于在更新操作时,无论实体对象的某些字段是否有变化,都会强制更新这些字段。这在某些业务场景下非常有用,比如更新时间戳字段,确保每次更新操作都会更新该字段。

使用场景:

当你需要在每次更新记录时,都更新某些特定的字段(如更新时间、版本号等),即使这些字段在实体对象中没有变化。

2>insertBatchSomeColumn
int insertBatchSomeColumn(List<T> entityList);
源码:
package com.baomidou.mybatisplus.extension.injector.methods;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import lombok.Setter;
import lombok.experimental.Accessors;
import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator;
import org.apache.ibatis.executor.keygen.KeyGenerator;
import org.apache.ibatis.executor.keygen.NoKeyGenerator;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;import java.util.List;
import java.util.function.Predicate;/*** 批量新增数据,自选字段 insert* <p> 不同的数据库支持度不一样!!!  只在 mysql 下测试过!!!  只在 mysql 下测试过!!!  只在 mysql 下测试过!!! </p>* <p> 除了主键是 <strong> 数据库自增的未测试 </strong> 外理论上都可以使用!!! </p>* <p> 如果你使用自增有报错或主键值无法回写到entity,就不要跑来问为什么了,因为我也不知道!!! </p>* <p>* 自己的通用 mapper 如下使用:* <pre>* int insertBatchSomeColumn(List<T> entityList);* </pre>* </p>** <li> 注意: 这是自选字段 insert !!,如果个别字段在 entity 里为 null 但是数据库中有配置默认值, insert 后数据库字段是为 null 而不是默认值 </li>** <p>* 常用的 {@link Predicate}:* </p>** <li> 例1: t -> !t.isLogicDelete() , 表示不要逻辑删除字段 </li>* <li> 例2: t -> !t.getProperty().equals("version") , 表示不要字段名为 version 的字段 </li>* <li> 例3: t -> t.getFieldFill() != FieldFill.UPDATE) , 表示不要填充策略为 UPDATE 的字段 </li>** @author miemie* @since 2018-11-29*/
public class InsertBatchSomeColumn extends AbstractMethod {/*** 字段筛选条件*/@Setter@Accessors(chain = true)private Predicate<TableFieldInfo> predicate;/*** 默认方法名*/public InsertBatchSomeColumn() {super("insertBatchSomeColumn");}/*** 默认方法名** @param predicate 字段筛选条件*/public InsertBatchSomeColumn(Predicate<TableFieldInfo> predicate) {super("insertBatchSomeColumn");this.predicate = predicate;}/*** @param name      方法名* @param predicate 字段筛选条件* @since 3.5.0*/public InsertBatchSomeColumn(String name, Predicate<TableFieldInfo> predicate) {super(name);this.predicate = predicate;}@SuppressWarnings("Duplicates")@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;SqlMethod sqlMethod = SqlMethod.INSERT_ONE;List<TableFieldInfo> fieldList = tableInfo.getFieldList();String insertSqlColumn = tableInfo.getKeyInsertSqlColumn(true, null, false) +this.filterTableFieldInfo(fieldList, predicate, TableFieldInfo::getInsertSqlColumn, EMPTY);String columnScript = LEFT_BRACKET + insertSqlColumn.substring(0, insertSqlColumn.length() - 1) + RIGHT_BRACKET;String insertSqlProperty = tableInfo.getKeyInsertSqlProperty(true, ENTITY_DOT, false) +this.filterTableFieldInfo(fieldList, predicate, i -> i.getInsertSqlProperty(ENTITY_DOT), EMPTY);insertSqlProperty = LEFT_BRACKET + insertSqlProperty.substring(0, insertSqlProperty.length() - 1) + RIGHT_BRACKET;String valuesScript = SqlScriptUtils.convertForeach(insertSqlProperty, "list", null, ENTITY, COMMA);String keyProperty = null;String keyColumn = null;// 表包含主键处理逻辑,如果不包含主键当普通字段处理if (tableInfo.havePK()) {if (tableInfo.getIdType() == IdType.AUTO) {/* 自增主键 */keyGenerator = Jdbc3KeyGenerator.INSTANCE;keyProperty = tableInfo.getKeyProperty();// 去除转义符keyColumn = SqlInjectionUtils.removeEscapeCharacter(tableInfo.getKeyColumn());} else {if (null != tableInfo.getKeySequence()) {keyGenerator = TableInfoHelper.genKeyGenerator(this.methodName, tableInfo, builderAssistant);keyProperty = tableInfo.getKeyProperty();keyColumn = tableInfo.getKeyColumn();}}}String sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), columnScript, valuesScript);SqlSource sqlSource = super.createSqlSource(configuration, sql, modelClass);return this.addInsertMappedStatement(mapperClass, modelClass, methodName, sqlSource, keyGenerator, keyProperty, keyColumn);}}
功能:

这个方法用于批量插入实体对象,但只插入实体对象中指定的某些字段。这在需要批量插入数据,但又不希望插入所有字段时非常有用。

使用场景:

当你需要批量插入数据,并且希望只插入实体对象中的部分字段,以提高插入效率或保护敏感数据。

3>logicDeleteByIdWithFill
int logicDeleteByIdWithFill(T entity);
源码:
package com.baomidou.mybatisplus.extension.injector.methods;import com.baomidou.mybatisplus.core.enums.SqlMethod;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;import java.util.List;import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;/*** 根据 id 逻辑删除数据,并带字段填充功能* <p>注意入参是 entity !!! ,如果字段没有自动填充,就只是单纯的逻辑删除</p>* <p>* 自己的通用 mapper 如下使用:* <pre>* int deleteByIdWithFill(T entity);* </pre>* </p>** @author miemie* @since 2018-11-09* @deprecated 3.5.0 {@link com.baomidou.mybatisplus.core.injector.methods.DeleteById}*/
@Deprecated
public class LogicDeleteByIdWithFill extends AbstractMethod {public LogicDeleteByIdWithFill() {super("deleteByIdWithFill");}/*** @param name 方法名* @since 3.5.0*/public LogicDeleteByIdWithFill(String name) {super(name);}@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {String sql;SqlMethod sqlMethod = SqlMethod.LOGIC_DELETE_BY_ID;if (tableInfo.isWithLogicDelete()) {List<TableFieldInfo> fieldInfos = tableInfo.getFieldList().stream().filter(TableFieldInfo::isWithUpdateFill).filter(f -> !f.isLogicDelete()).collect(toList());if (CollectionUtils.isNotEmpty(fieldInfos)) {String sqlSet = "SET " + fieldInfos.stream().map(i -> i.getSqlSet(EMPTY)).collect(joining(EMPTY))+ tableInfo.getLogicDeleteSql(false, false);sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlSet, tableInfo.getKeyColumn(),tableInfo.getKeyProperty(), tableInfo.getLogicDeleteSql(true, true));} else {sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), sqlLogicSet(tableInfo),tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),tableInfo.getLogicDeleteSql(true, true));}} else {sqlMethod = SqlMethod.DELETE_BY_ID;sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), tableInfo.getKeyColumn(),tableInfo.getKeyProperty());}SqlSource sqlSource = super.createSqlSource(configuration, sql, modelClass);return addUpdateMappedStatement(mapperClass, modelClass, methodName, sqlSource);}}
功能:

这个方法用于逻辑删除记录,并填充实体对象中的某些字段。逻辑删除意味着不是真正从数据库中删除记录,而是通过更新某个字段(如 deleted 字段)来标记记录已被删除。

使用场景:

当你需要实现逻辑删除功能,并且希望在删除操作时自动填充实体对象中的某些字段(如删除时间、删除人等)。

使用提示

  1. 在使用这些选装件之前,确保你的项目中已经正确配置了 Sql 注入器。
  2. 这些方法通常需要在 Mapper 接口中显式声明,以便 Mybatis-Plus 能够识别并生成相应的 SQL 语句。
  3. 每个选装件都有其特定的使用场景,根据业务需求选择合适的方法。
  4. 在实际使用中,可能需要结合实体对象的注解(如 @TableField、@TableLogic 等)来实现更复杂的功能。

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

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

相关文章

【PLW003】设备器材云端管理平台v1.0(SpringBoot+Mybatis+NodeJS+MySQL前后端分离)

设备器材云端管理平台是一种专为各种设备&#xff08;如教育行业中的实验设备、建筑行业中的施工设备等&#xff09;租赁或共享孵化的数字化管理工具&#xff0c;旨在融合数字化手段&#xff0c;提高各种设备器材的管理效率、 确保设备的安全稳定运行&#xff0c;并优化资源使用…

【Godot4.3】基于状态切换的游戏元素概论

提示 本文的设想性质比较大,只是探讨一种设计思路。完全理论阶段&#xff0c;不可行就当是闹了个笑话O(∩_∩)O哈哈~但很符合我瞎搞的气质。 概述 一些游戏元素&#xff0c;其实是拥有多个状态的。比如一个宝箱&#xff0c;有打开和关闭两个状态。那么只需要设定两个状态的图…

日志系统第五弹:同步日志器模块

日志系统第五弹&#xff1a;同步日志器模块 一、Logger类的设计1.功能2.如何打印日志3.设计 - - - 成员变量1.日志输出限制等级2.资源整合3.唯一标识4.互斥锁 4.设计 - - - 成员函数1.对外的日志打印接口2.抽象的日志实际落地接口3.其他接口 5.Logger类的框架 二、Logger类的实…

springboot地方特色美食分享系统-计算机毕业设计源码02383

摘要 本论文主要论述了如何使用SpringBoot技术开发一个地方特色美食分享系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述地方特色美食分享系统的当前背景以…

DHCP服务器搭建

1. DHCP工作原理 DHCP动态分配IP地址&#xff0c;客户端广播&#xff0c;服务端单播 2. DHCP服务器安装 2.1 安装DHCP # yum install -y dhcp-server 2.2 修改配置文件 # cd /etc/dhcp/ # ls # vi dhcpd.conf dhcpd.conf 主配置文件 第一行&#xff1a;全局dhcp服务器地…

240922-Ollama使用Embedding实现RAG

A. 最终效果 B. 参考代码 # [嵌入模型 Ollama 博客 - Ollama 中文](https://ollama.org.cn/blog/embedding-models)# 步骤1&#xff1a;生成嵌入import ollama import chromadbdocuments ["Llamas are members of the camelid family meaning theyre pretty closely re…

Golang | Leetcode Golang题解之第423题从英文中重建数字

题目&#xff1a; 题解&#xff1a; func originalDigits(s string) string {c : map[rune]int{}for _, ch : range s {c[ch]}cnt : [10]int{}cnt[0] c[z]cnt[2] c[w]cnt[4] c[u]cnt[6] c[x]cnt[8] c[g]cnt[3] c[h] - cnt[8]cnt[5] c[f] - cnt[4]cnt[7] c[s] - cnt[6]…

手势识别-Yolov5模型-自制数据集训练

1、源码下载&#xff1a; 大家可以直接在浏览器搜索yolov5即可找到官方链接&#xff0c;跳转进github进行下载&#xff1a; 这里对yolov5模型补充说明一下&#xff0c;它是存在较多版本的&#xff0c;具体信息可在master->tags中查看&#xff0c;大家根据需要下载。这些不同…

二叉树(链式存储)

文章目录 一、树的基础概念二、二叉树2.1 概念 性质2.2 二叉树的存储2.2 二叉树的基本操作手动创建一棵二叉树遍历&#xff1a;前、中、后、层序获取树中节点的个数获取叶子节点的个数获取第K层节点的个数获取二叉树的高度检测值为value的元素是否存在判断一棵树是不是完全二叉…

青岛特某电新能源有限公司-充电业务流程及数据交互规范-集控前置-精简版V1.0

1 范围 本流程规定了特某电充电终端所属的集控器与特某电云平台前置之间的充电相关业务流程&#xff0c;明确两端之间的请求和响应。 2 术语 云平台&#xff1a;云平台是提供包括充电设备接入&#xff0c;充电设备信息采集&#xff0c;充电设备管 理&#xff0c;充电设备运维…

Gin框架入门(1)--路由搭建与Json处理

背景知识 为什么要使用Go框架 如果不使用框架&#xff0c;在创建服务器和调用端口时会遇到各种各样“奇怪”的问题&#xff08;就是出错的排查方向可能达到十几种&#xff09;&#xff0c;而且这些问题很难有相似性。同时作为适应于微服务的一门语言&#xff0c;代码的规范化…

构建高可用和高防御力的云服务架构第三部分:ECS集群(3/5)

ECS&#xff08;Elastic Compute Service&#xff09;是一种基础云计算服务&#xff0c;它提供了可伸缩的计算能力&#xff0c;允许用户在不需要预先购买硬件的情况下&#xff0c;根据需求快速扩展或缩减资源。ECS在云计算中的作用主要体现在提供虚拟化的服务器&#xff0c;用户…

食探秘:Spring Boot校园周边美食发现平台

第三章 系统设计 3.1 系统概要设计 本校园周边美食探索及分享平台选择B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式。适合在互联网上进行操作&#xff0c;只要用户能连网&#xff0c;任何时间、任何地点都可以进行系统的操作使用。系统工作原理图如图3-1所…

专业学习|动态规划(概念、模型特征、解题步骤及例题)

一、引言 &#xff08;一&#xff09;从斐波那契数列引入自底向上算法 &#xff08;1&#xff09;知识讲解 &#xff08;2&#xff09;matlap实现递归 &#xff08;3&#xff09;带有备忘录的遗传算法 &#xff08;4&#xff09;matlap实现带有备忘录的递归算法 “&#xff1…

linux入门介绍(通俗易懂,快速理解linux)

什么是操作系统&#xff1f; 操作系统&#xff08;Operating System&#xff0c;简称OS&#xff09;是管理和控制计算机硬件与软件资源的计算机程序&#xff0c;是配置在计算机硬件上的第一层软件&#xff0c;任何其它软件都必须在操作系统的支持下才能运行。 简单来说&#…

【LeetCode热题100】位运算

这篇博客先介绍了常见位运算操作&#xff0c;然后记录了关于位运算的几道题&#xff0c;包括判定字符是否唯一、丢失的数字、两整数之和、只出现一次的数字2、消失的两个数字。 在这一部分&#xff0c;我们不妨先来总结一下常见位运算操作&#xff1a; 1.基础位运算 >>…

fastadmin数据库创建说明文档

文章目录 数据库根据字段类型特殊字段以特殊字符结尾的规则注释说明 实例数字下拉列表日期时间文本框权重category_id --单选下拉框category_ids --多选下拉框deletetime --对应回收站status --对应tab常见问题 参考完结 数据库 这里提供的是数据库表字段规则在你创建表时使用…

Linux内核移植实战总结

直接参考【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.81 本文仅作为个人笔记使用&#xff0c;方便进一步记录自己的实践总结。 前两章我们简单了解了一下 Linux 内核顶层 Makefile 和 Linux 内核的启动流程&#xff0c;本章我们就来学习一下如何将 NXP官方提供的 Linux 内核移…

17.1ksm关注指标讲解 pod和node状态的统计

本节重点介绍 : 主要的应用 看状态数个数 根据13105大盘模板看ksm指标 节点指标pod和容器指标资源对象按namespace分布指标其他资源指标 主要的应用 看状态&#xff0c;举例图片数个数&#xff0c;举例图片 根据大盘模板 查看指标 https://grafana.com/grafana/dashboard…

Tomcat靶场攻略

一.CVE-2017-12615 1.首页抓包&#xff0c;修改为 PUT 方式提交 ,将jsp木马写到数据包中 2.哥斯拉默认秘钥连接 二.后台弱⼝令部署war包 1.制作WAR包,上传 将JSP⽊⻢压缩为ZIP格式&#xff0c;然后修改后缀为war 2.文件上传成功后&#xff0c;默认会在网站根目录下生成和wa…