myBatis-plus自动填充插件
在 MyBatis-Plus 3.x 中,自动填充的插件方式发生了变化。现在推荐使用 MetaObjectHandler 接口的实现类来定义字段的填充逻辑。以下是使用 MyBatis-Plus 3.x 自动填充的基本步骤:
1.基本配置
1.1添加 Maven 依赖:
确保你的 Maven 依赖中使用的是 MyBatis-Plus 3.x 版本。
<dependencies><!-- MyBatis-Plus 核心依赖 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>最新版本</version></dependency><!-- 其他依赖... -->
</dependencies>
1.2 配置 MyBatis-Plus 自动填充
1.2.1使用@Component注解
创建一个实现 MetaObjectHandler 接口的配置类,用于定义字段填充逻辑。
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());}@Overridepublic void updateFill(MetaObject metaObject) {this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());}
}
这种方式是 MyBatis-Plus 3.x 中推荐的字段自动填充方式。在这个示例中,MyMetaObjectHandler 类上添加了 @Component 注解,确保 Spring Boot 能够自动扫描到并注册为 Bean。这样,MyBatis-Plus 在执行插入和更新操作时会自动调用 MetaObjectHandler 中的对应方法进行字段填充
1.2.1 使用@Bean+@Configuration注解
当然也可以使用@bean的方式在mybatisConfig里面注入
import com.sky.handler.MyMetaObjectHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyBatisPlusConfig {@Beanpublic MyMetaObjectHandler myMetaObjectHandler() {return new MyMetaObjectHandler();}
}
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {log.info("开始插入时自动填充");this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());}@Overridepublic void updateFill(MetaObject metaObject) {log.info("开始更新时自动填充");this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());}
}
但是用这种方式的时候需要注意MyMetaObjectHandler这个类前面不能加Component,否则会造成bean冲突。
定义实体类:
在实体类中定义需要自动填充的字段:
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;import java.time.LocalDateTime;@Data
@TableName("your_table_name")
public class YourEntity {@TableIdprivate Long id;private String name;// 其他字段省略...// createTime 和 updateTime 字段将由 MyBatis-Plus 自动填充@TableField(fill = FieldFill.INSERT)private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private LocalDateTime updateTime;
}
确保你的实体类中的字段类型和配置的 MetaObjectHandler 中的类型一致。
。
这样达到的实际效果就是
我们在封装好入库的对象的时候,没有setUpdateTime这个属性,那么执行intsert 和 update操作的之后,数据库中也会向UpdateTime存入值。
下面我们需要对一些细节说明一下
2. 严格模式与非严格模式
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
在这个示例中,MyMetaObjectHandler 实现了 MetaObjectHandler 接口,并在 insertFill 和 updateFill 方法中定义了字段填充的逻辑。strictInsertFill 和 strictUpdateFill 方法用于严格模式的字段填充。
非严格模式: 在非严格模式下,字段填充通常会在任何情况下都执行,即使字段的值已经被手动设置或者数据库中已经有了一个值。这样可能导致字段值被多次更新,。
严格模式: 相比之下,严格模式会更加谨慎。在严格模式下,字段填充只会在满足一定条件的情况下才执行。例如,在插入操作时,只有在字段的值为 null 时才会进行填充。在更新操作时,只有在字段的值为 null 或者被标记为需要更新时才会进行填充。
3.自动插入的时机
上述的自动填充操作是发生在数据库层面的
具体说是在 MyBatis 执行 SQL 语句时,MyBatis-Plus 框架会拦截这些 SQL 操作,根据配置的自动填充规则来动态生成相应的字段值,然后执行相应的 SQL 操作。这样可以在数据库层面确保这些字段的值符合预期。
插入操作: 当执行插入 SQL 语句时,MyBatis-Plus 拦截器会在插入前执行 MetaObjectHandler 的 insertFill 方法,填充相应字段的值,然后将填充后的 SQL 语句发送给数据库执行。
更新操作: 同理,对于更新 SQL 语句,MyBatis-Plus 会在更新前执行 MetaObjectHandler 的 updateFill 方法,填充相应字段的值,然后将填充后的 SQL 语句发送给数据库执行。
这样做的好处是在数据库层面确保了字段填充的一致性,避免了手动在 Service 层面或者 Controller 层面进行填充,减少了代码冗余和错误的可能性。这也是 MyBatis-Plus 提供的一种便捷的开发方式,使得开发者可以更专注于业务逻辑而不用过多关心数据库层面的操作。
注意:上述操作并不是废话,我们来看这样一个例子(这个例子是我实际项目中的例子,我们只需要关注自动填充相关的部分就可以)
实体类
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("employee")
public class Employee implements Serializable {private static final long serialVersionUID = 1L;@TableId(type = IdType.AUTO)//自增主键private Long id;@TableField(insertStrategy = FieldStrategy.NOT_EMPTY)private String username;@TableField(insertStrategy = FieldStrategy.NOT_EMPTY)private String name;@TableField(insertStrategy = FieldStrategy.NOT_EMPTY)private String password;@TableField(insertStrategy = FieldStrategy.NOT_EMPTY)private String phone;@TableField(insertStrategy = FieldStrategy.NOT_EMPTY)@EnumValue()private String sex;@TableField(value = "id_number",insertStrategy = FieldStrategy.NOT_NULL)private String idNumber;private EmployeeStatus status;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")@TableField(fill = FieldFill.INSERT)//表示该字段只会在插入的填充private LocalDateTime createTime;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")@TableField(fill = FieldFill.INSERT_UPDATE)//表示这个字段只会在传入和更改的时候都会填充private LocalDateTime updateTime;@TableField(fill = FieldFill.INSERT)//表示该字段只会在插入的填充private Long createUser;@TableField(fill = FieldFill.INSERT_UPDATE)//表示该字段只会在插入的填充private Long updateUser;
}}
我的自动填充是这样写的
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {log.info("开始插入时自动填充");this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class,LocalDateTime.now());}@Overridepublic void updateFill(MetaObject metaObject) {log.info("开始更新时自动填充");this.strictUpdateFill(metaObject, "updateTime",LocalDateTime.class, LocalDateTime.of(2022,12,30,5,6,0));}
}
我这里写了一个测试类
@SpringBootTest
class SkyApplicationTest {@ResourceEmployeeMapper employeeMapper;@Testpublic void test() {LambdaUpdateWrapper<Employee> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();lambdaUpdateWrapper.eq(Employee::getName,"张三");lambdaUpdateWrapper.set(Employee::getPhone,"2222222222");Employee employee = new Employee();employee.setPhone("111111111");employeeMapper.update(employee,lambdaUpdateWrapper);System.out.println("");}}
那么这个sql执行的结果是什么?
UPDATEemployee SETphone='111111111',update_time='2022-12-30T05:06',update_user=null,phone='2222222222' WHERE(name = '张三');
这个sql为什么是这样的
我们先看phone这个字段
phone这个字段是没有设置自动填充的,但是两个入参,实体类Employee,和更新条件LambdaUpdateWrapper都对phone都对phone设置了值。
通过sql我们不难发现,mybatis-plus会先根据实体类中不为null的值进行set,然后再写入更新条件中的set
所以,最后更新到数据库里,谁写在SQL语句的最后,数据库里的值就会是谁。
下面
update_time='2022-12-30T05:06',update_user=null,
这两个字段都是自动填充设置的,其中update_time=‘2022-12-30T05:06’,是我设置了固定值,而update_user=null,是因为我没在MyMetaObjectHandler里设置值的原因,才会赋值为null.
那么现在的问题是自动插入的时机在哪呢?
我们不妨构建这样的例子
@Overridepublic void insertFill(MetaObject metaObject) {log.info("开始插入时自动填充");this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class,LocalDateTime.now());this.strictInsertFill(metaObject,"updateUser",Long.class,1L);this.strictInsertFill(metaObject,"createUser",Long.class,1L);}@Overridepublic void updateFill(MetaObject metaObject) {log.info("开始更新时自动填充");this.strictUpdateFill(metaObject, "updateTime",LocalDateTime.class, LocalDateTime.of(2022,12,30,5,6,0));this.strictInsertFill(metaObject,"updateUser",Long.class,1L);}
自动填充的时候,uptdateUser会被填入1L
@Testpublic void test() {LambdaUpdateWrapper<Employee> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();lambdaUpdateWrapper.eq(Employee::getName,"张三");lambdaUpdateWrapper.set(Employee::getUpdateUser,2L);Employee employee = new Employee();employee.setUpdateUser(3L);employeeMapper.update(employee,lambdaUpdateWrapper);System.out.println("");}
而在测试类中。实体类Employee中的updateUser值是3L
查询条件中的updateUser是2L
那么形成的SQL是什么样的呢?
/*17 2023-12-17 16:52:32 */UPDATEemployee SETupdate_time='2022-12-30T05:06',update_user=3,update_user=2 WHERE(name = '张三');
先update_user = 3,后update_user = 2,这个之前就解释过了
但是update = 1怎么没有呢?
这是因为前面说的我们在设置自动填充时遵循的时严格模式的插入,当执行update操作的时候,如果该实体类中的updat_user不为null,就不会触发字段填充。
严格模式下的填充规则
插入时填充规则(INSERT):
当执行插入操作时,只有在实体类的字段的值为 null 时才进行填充。
如果实体类字段的值不为 null,则填充操作会被忽略。
更新时填充规则(UPDATE):
当执行更新操作时,只有在字段的值为 null 或者字段被标记为需要更新时才进行填充。
如果字段的值不为 null,且字段没有被标记为需要更新,填充操作会被忽略。
一定一定注意,是实体类中的字段值为null
我们将测试类更改一下:
@SpringBootTest
class SkyApplicationTest {@ResourceEmployeeMapper employeeMapper;@Testpublic void test() {LambdaUpdateWrapper<Employee> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();lambdaUpdateWrapper.eq(Employee::getName,"张三");lambdaUpdateWrapper.set(Employee::getUpdateUser,2L);Employee employee = new Employee();
// employee.setUpdateUser(3L);employeeMapper.update(employee,lambdaUpdateWrapper);System.out.println("");}}
我们将实体类中updateUser设置为null
你会发现生成的SQL语言是
UPDATEemployee SETupdate_time='2022-12-30T05:06',update_user=1,update_user=2 WHERE(name = '张三');
会发现,自动填充是触发了的。
并且在lambdaUpdateWrapper这个更新条件的前面。这是因为本质上,自动填充是给实体类的update_time赋值的。
此外还有一个注意点,有一种情况也会导致自动填充失效。
在mybatispluss的官网也有说明。
https://baomidou.com/pages/4c6bcf/
看下面这个例子
@SpringBootTest
class SkyApplicationTest {@ResourceEmployeeMapper employeeMapper;@Testpublic void test() {LambdaUpdateWrapper<Employee> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();lambdaUpdateWrapper.eq(Employee::getName,"张三");lambdaUpdateWrapper.set(Employee::getUpdateUser,2L);// Employee employee = new Employee();
// employee.setUpdateUser(3L);employeeMapper.update(null,lambdaUpdateWrapper);System.out.println("");}}
他的sql实际为
UPDATEemployee SETupdate_user=2 WHERE(name = '张三');
之所以会这样,update的实体类入参是null,自动填充根本就没有启动。
所以当我们的实体类在定义的时候使用了@TableField(fill = FieldFill.*****)的时候,使用mybatis-plus自带的update方法的时候一定不能传null的实体类。可以传new my_entity()过来。
相关文章:

myBatis-plus自动填充插件
在 MyBatis-Plus 3.x 中,自动填充的插件方式发生了变化。现在推荐使用 MetaObjectHandler 接口的实现类来定义字段的填充逻辑。以下是使用 MyBatis-Plus 3.x 自动填充的基本步骤: 1.基本配置 1.1添加 Maven 依赖: 确保你的 Maven 依赖中使…...
746. 使用最小花费爬楼梯 --力扣 --JAVA
题目 给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。 请你计算并返回达到楼梯顶部的最低花费。 解题思路 到…...
使用Verdaccio搭建私有npm仓库
搭建团队的私有仓库,保证团队组件的安全维护和私密性,是进阶前端开发主管路上,必不可少的一项技能。 一、原理 我们平时使用npm publish进行发布时,上传的仓库默认地址是npm,通过Verdaccio工具在本地新建一个仓库地址…...

87 GB 模型种子,GPT-4 缩小版,超越ChatGPT3.5,多平台在线体验
瞬间爆火的Mixtral 8x7B 大家好,我是老章 最近风头最盛的大模型当属Mistral AI 发布的Mixtral 8x7B了,火爆程度压过Google的Gemini。 缘起是MistralAI二话不说,直接在其推特账号上甩出了一个87GB的种子 随后Mixtral公布了模型的一些细节&am…...
Golang 数组 移除元素 双指针法 leetcode27 小记
文章目录 移除元素 leetcode27暴力解法双指针法1. 快慢指针2. 双向指针 移除元素 leetcode27 go中数据类型的分类: 1.值类型:int、float、bool、string、数组、结构体 2.引用类型:指针、切片、map、管道、接口 由于切片为引用类型,…...
c# OpenCV 图像裁剪、调整大小、旋转、透视(三)
图像裁剪、调整大小、旋转、透视图像处理基本操作。 croppedImage 图像裁剪Cv2.Resize() 调整图像大小图像旋转 Cv2.Rotate()旋转Cv2.Flip()翻转Cv2.WarpAffine()任意角度旋转Cv2.GetAffineTransform()透视 一、图像裁剪 // 读取原始图像 Mat image new Mat("1.png&q…...

Kafka相关知识
一、kafka架构 Kafka基础知识 Kafka是最初由Linkedin公司开发,是一个分布式、分区的、多副本的、多生产者、多订阅者,基于zookeeper协 调的分布式日志系统(也可以当做MQ系统),常见可以用于webynginx日志、访问日志,消息服务等等&…...

gitlab 通过svn hook 触发
jenkins 起一个item 配置: 我选的自由风格的 源码管理配置 先选subversion 就是svn类型 url 设置project 的路径, 注意是工程,不是svn 顶层 添加一个账户来进行pull 等操作 选择添加的账号 构建触发器: ,重要的是要自…...

设计模式详解---单例模式
1. 设计模式详解 单例模式是一种创建对象的设计模式,它确保一个类只有一个实例,并提供全局访问点以获取该实例。 在单例模式中,类负责创建自己的唯一实例,并确保任何其他对象只能访问该实例。这对于需要共享状态或资源的情况非常有…...

毕设之-Hlang后端架构-双系统交互
文章目录 前言交互流程基本流程约定公钥人人中台携带公钥获取私钥私钥生成人人中台携带私钥访问私钥验证(博客系统) 调试演示总结 前言 前天我们完成了基本的整合,但是还没有整合到我们的业务系统,也就是博客系统。本来昨天要搞一…...

什么同源策略?
同源 同源指的是URL有相同的协议、主机名和端口号。 同源策略 同源策略指的是浏览器提供的安全功能,非同源的RUL之间不能进行资源交互 跨域 两个非同源之间要进行资源交互就是跨域。 浏览器对跨域请求的拦截 浏览器是允许跨域请求的,但是请求返回…...

破译模式:模式识别在计算机视觉中的作用
一、介绍 在当代数字领域,计算机视觉中的模式识别是关键的基石,推动着众多技术进步和应用。本文探讨了计算机视觉中模式识别的本质、方法、应用、挑战和未来趋势。通过使机器能够识别和解释视觉数据中的模式,模式识别不仅推动了计算机视觉领域…...

c语言-全局变量与局部变量
目录 1、(作用)域的概念 2、全局与局部的相对性 3、生命周期 3、静态变量static 结语: 前言: 在c语言中,全局变量的可见范围是整个工程,而局部变量的可见范围从该变量被定义到该作用域结束,…...

【Spring】00 入门指南
文章目录 1.简介2.概念1)控制反转(IoC)2)依赖注入(DI) 3.核心模块1)Spring Core2)Spring AOP3)Spring MVC4)Spring Data5)Spring Boot 4.编写 Hel…...

BIM 技术:CIM (City Information Modeling) 1-7 级
本心、输入输出、结果 文章目录 BIM 技术:CIM (City Information Modeling) 1-7 级前言城市信息模型(CIM)概述城市信息模型分级介绍CIM 1CIM 2CIM 3CIM 4CIM 5CIM 6CIM 7 花有重开日,人无再少年实践是检验真…...

c++ websocket 协议分析与实现
前言 网上有很多第三方库,nopoll,uwebsockets,libwebsockets,都喜欢回调或太复杂,个人只需要在后端用,所以手动写个; 1:环境 ubuntu18 g(支持c11即可) 第三方库:jsoncpp,openssl 2:安装 jsoncpp 读取json 配置文件 用 自动安装 网…...

kali虚拟机无网络
1.查看虚拟机的网卡模式 在虚拟机设置里,一般选择桥接模式,也可以选择NAT模式。 2、你的IP地址是否写死了(设置为静态IP) vim编辑模式下的命令: 按a或i进入编辑模式,然后按esc键退出编辑模式,s…...

Unity2023.3(Unity6)版本开始将可以发布WebGPU
翻译一段官网上的话: 利用Unity 2023.3(正式发布时应该称为Unity6)中最新的WebGPU图形API集成,尝试最大限度的提升您的网络游戏的真实感。 通过与谷歌的战略合作,Unity实时3D平台的强大的图形功能现在为图形丰富的网络游戏进行微调࿰…...
计算机网络期末考试A卷及答案
一、选择题(30分,每题1分) 世界上第一个网络系统是( C )。 A、ENIAC B、以太网 C、ARPANET D、DECNET 2.在常用的传输介质中,( C )的带宽最宽、信号传输衰减最小、抗干扰能力最强。 A.双绞线 …...

<蓝桥杯软件赛>零基础备赛20周--第10周--二分
报名明年4月蓝桥杯软件赛的同学们,如果你是大一零基础,目前懵懂中,不知该怎么办,可以看看本博客系列:备赛20周合集 20周的完整安排请点击:20周计划 每周发1个博客,共20周(读者可以按…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

大话软工笔记—需求分析概述
需求分析,就是要对需求调研收集到的资料信息逐个地进行拆分、研究,从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要,后续设计的依据主要来自于需求分析的成果,包括: 项目的目的…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1
每日一言 生活的美好,总是藏在那些你咬牙坚持的日子里。 硬件:OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写,"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...

2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...