功能:在新增护理项目的时候,创建人,创建时间和修改时间字段会自动拦截填充,这些公共字段可以省去我们一个一个处理的麻烦

依靠:AutoFillInterceptor拦截器,MybatisConfig配置类

第一步:我们需要借助一个MybatisConfig,@configuration标志着这是一个配置类,我们需要将autoFillInterceptor放在配置类中并用@Bean注解将这个配置类交给spring容器gu

第二步:了解配置类的原理,也就是AutoFillInterceptor,这个拦截器的代码大部分是固定的我用只需要了解它的逻辑,在需要的时候复制代码并根据需求修改

package com.zzyl.intercept;// 引入工具类和依赖
import cn.hutool.core.util.ObjectUtil;
import com.zzyl.utils.EmptyUtil;
import com.zzyl.utils.UserThreadLocal;
import org.apache.ibatis.binding.MapperMethod;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.springframework.stereotype.Component;import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Properties;// 声明这是一个MyBatis拦截器,拦截Executor的update方法
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
@Component // 声明为Spring组件
public class AutoFillInterceptor implements Interceptor {// 常量定义:字段名private static final String CREATE_BY = "createBy";   // 创建人字段名private static final String UPDATE_BY = "updateBy";   // 更新人字段名private static final String CREATE_TIME = "createTime"; // 创建时间字段名private static final String UPDATE_TIME = "updateTime"; // 更新时间字段名// 拦截逻辑核心方法@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 获取方法参数:MappedStatement和SQL参数对象Object[] args = invocation.getArgs();MappedStatement ms = (MappedStatement) args[0];  // 获取SQL映射信息SqlCommandType sqlCommandType = ms.getSqlCommandType(); // 获取SQL操作类型(INSERT/UPDATE等)Object parameter = args[1];  // 获取SQL参数对象// 仅当参数和SQL类型有效时处理if (parameter != null && sqlCommandType != null) {Long userId = loadUserId();  // 获取当前用户ID(从ThreadLocal)// 处理INSERT操作if (SqlCommandType.INSERT.equals(sqlCommandType)) {// 批量插入场景(参数是ParamMap且包含list字段)if (parameter instanceof MapperMethod.ParamMap) {MapperMethod.ParamMap paramMap = (MapperMethod.ParamMap) parameter;ArrayList list = (ArrayList) paramMap.get("list"); // 获取批量数据列表list.forEach(v -> {// 为每条数据设置创建人、创建时间、更新时间setFieldValByName(CREATE_BY, userId, v);setFieldValByName(CREATE_TIME, LocalDateTime.now(), v);setFieldValByName(UPDATE_TIME, LocalDateTime.now(), v);});paramMap.put("list", list); // 更新修改后的参数} else {// 单条插入场景setFieldValByName(CREATE_BY, userId, parameter);setFieldValByName(CREATE_TIME, LocalDateTime.now(), parameter);setFieldValByName(UPDATE_TIME, LocalDateTime.now(), parameter);}} // 处理UPDATE操作else if (SqlCommandType.UPDATE.equals(sqlCommandType)) {// 设置更新人和更新时间setFieldValByName(UPDATE_BY, userId, parameter);setFieldValByName(UPDATE_TIME, LocalDateTime.now(), parameter);}}// 继续执行原始SQL操作return invocation.proceed();}/*** 通过反射设置实体对象的字段值* @param fieldName  字段名(如createBy)* @param fieldVal   字段值(如用户ID)* @param parameter  实体对象*/private void setFieldValByName(String fieldName, Object fieldVal, Object parameter) {// 使用MyBatis的MetaObject操作对象属性MetaObject metaObject = SystemMetaObject.forObject(parameter);// 如果是createBy字段且已有值,则跳过(避免覆盖)if (fieldName.equals(CREATE_BY)) {Object value = metaObject.getValue(fieldName);if (ObjectUtil.isNotEmpty(value)) {return;}}// 如果字段存在setter方法,则设置值if (metaObject.hasSetter(fieldName)) {metaObject.setValue(fieldName, fieldVal);}}// 包装目标对象(Executor),返回代理对象@Overridepublic Object plugin(Object target) {if (target instanceof Executor) {return Plugin.wrap(target, this); // MyBatis提供的包装方法}return target; // 非Executor类型直接返回}// 可读取配置文件属性(本例未使用)@Overridepublic void setProperties(Properties properties) {}/*** 获取当前用户ID(优先级:ThreadLocal用户ID → 管理用户ID → 默认值1)*/public static Long loadUserId() {Long userId = UserThreadLocal.getUserId(); // 从业务线程获取if (ObjectUtil.isNotEmpty(userId)) {return userId;}userId = UserThreadLocal.getMgtUserId(); // 从管理线程获取if (!EmptyUtil.isNullOrEmpty(userId)) {return userId;}return 1L; // 默认值}
}

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[创业之路-527]:什么是产品技术成熟度曲线?

产品技术成熟度曲线(Gartner Hype Cycle)是由全球知名咨询机构Gartner提出的工具,用于可视化展示新兴技术从诞生到成熟的发展轨迹,以及市场对其预期和实际采用趋势的变化。该曲线通过五个阶段刻画技术生命周期,帮助企业…

VScode对Ubuntu用root账号进行SSH远程连接开发

由于linux服务器大部分都是基于命令行的操作,缺乏比较方便好用的编辑工具,对于经常在linux服务器上做开发的同学来说直接在服务器上进行开发或配置文件的修改还不是特别的方便。虽然linux上有vi或vim比起图形化的编辑工具体验感还是不是很好。作为程序员…

【物联网】基于树莓派的物联网开发【20】——树莓派控制DHT11温湿度传感器实战

传感器概述 DHT11是一款有已校准数字信号输出的温湿度传感器。 其精度湿度5%RH, 温度2℃,量程湿度20-90%RH, 温度0~50℃。分为3个接口,分别为:VCC, DATA, GND。 产品图片主要用途 检测环境温湿度 GPIO控制DHT11温湿度传…

AI原生数据库:告别SQL的新时代来了?

在2025年的今天,生成式AI的浪潮正以前所未有的力量重塑着各行各业。从代码生成到艺术创作,大型语言模型(LLM)的能力边界不断被拓宽。现在,这股浪潮正涌向信息技术领域最古老、最核心的基石之一:数据库。一个…

题单【模拟与高精度】

P1042 [NOIP 2003 普及组] 乒乓球 P1042 [NOIP 2003 普及组] 乒乓球 - 洛谷 #include<bits/stdc.h> using namespace std;char C; string S; int n,A,B;void Work(int Lim) {for(char i:S){if(iW) A;if(iL) B;if(max(A,B)>Lim && abs(A-B)>2){cout<<…

数据结构学习基础和从包装类缓存到泛型擦除的避坑指南

目录 1.数据结构的概念和算法 1.1 数据结构的概念 1.2 数据结构的集合框架 1.3 算法 1.3.1 时间复杂度 1.3.2 空间复杂度 2.包装类 2.1 为什么需要包装类&#xff1f; 2.2 装箱和拆箱 3. 初识泛型 3.1 认识泛型 3.2 泛型类的使用 3.3 泛型的编译 3.4 通配符 3.4.1 …

网络安全基础知识【6】

什么是防火墙1.防火墙指的是一个由软件和硬件设备组合而成、在内部网和外部网之间、 专用网与公共网之间的界面上构造的保护屏障 2.防火墙实际上是一种隔离技术 3.防火墙重要的特征是增加了区域的概念防火墙的定义 隔离可信与不可信网络的设备/软件&#xff0c;基于策略控制流量…

Apache Doris数据库——大数据技术

Apache Doris一、简介1.1、Apache Doris简介1.2、Apache Doris 与传统大数据架构相比1.3、doris是java团队掌控大数据能力最优选择1.4、 OLTP&#xff08;在线事务处理&#xff09; 与 OLAP&#xff08;在线分析处理&#xff09;1.5、发展历程1.6、应用现状1.7、整体架构1.7.1、…

Conda和pip的使用记录

Conda和pip的使用记录一、创建新的 Conda 环境二、激活环境三、安装其他包&#xff08;可选&#xff09;四、查看已有环境五、删除环境&#xff08;可选&#xff09;⚙️ Conda 下载缓慢的解决方案&#xff08;推荐使用国内镜像&#xff09;&#x1f527; 方法一&#xff1a;**…

详解Python标准库之互联网数据处理

详解Python标准库之互联网数据处理 在互联网时代&#xff0c;数据的产生、传输和处理无处不在。从电子邮件的收发到 API 接口的数据交换&#xff0c;从二进制数据的编码到 MIME 类型的识别&#xff0c;Python 标准库提供了一整套强大的工具集&#xff0c;帮助开发者轻松应对各种…

适 配 器 模 式

前阵子&#xff0c;笔者在网上淘来一个二手显示屏来搭配我装好的主机&#xff0c;但是送到手上后我却找不到电源适配器的踪迹。于是我就在家找了根电源线接上了显示屏&#xff0c;倒是能亮&#xff0c;就是屏幕闪得和机关枪似的。这是因为我的显示屏需要12V的供电&#xff0c;我…

智慧零售商品识别准确率↑32%:陌讯多模态融合算法实战解析

原创声明本文为原创技术解析&#xff0c;核心技术参数与架构设计引用自《陌讯技术白皮书》&#xff0c;禁止任何形式的未经授权转载。一、行业痛点&#xff1a;智慧零售的 "看得见的障碍"在智慧零售场景中&#xff0c;从自助结算终端到智能货架管理&#xff0c;计算机…

Linux系统编程-gcc(黑马笔记)

1 gcc的编译流程gcc编译的整个过程并且整个过程下来的每个过程。并且给出了每个阶段产物和gcc命令。1.1 数据段合并其实就是因为“块” 一次是读多个字节而不是一个字节&#xff0c;所以会将一些地址段合并从而提升效率1.2 地址回填这张图也有些问题&#xff0c;正确的结论是:地…

Git踩坑

文章目录前言❓问题分析&#xff1a;为什么你的提交会“覆盖”别人的代码&#xff1f;✅ 正确的代码提交流程&#xff08;结合你原文的说明&#xff09;**1. 确认自己在正确的分支上****2. 从主开发分支&#xff08;如 dev&#xff09;拉取最新代码并合并****3. 解决冲突&#…

sqli-labs:Less-20关卡详细解析

1. 思路&#x1f680; 本关的SQL语句为&#xff1a; $sql"SELECT * FROM users WHERE username$cookee LIMIT 0,1";注入类型&#xff1a;字符串型&#xff08;单引号包裹&#xff09;、GET操作提示&#xff1a;参数需以闭合关键参数&#xff1a;cookee php输出语句…

基于LevitUnet的超声图像分割

完整项目包获取&#xff1a;点击文末名片本项目旨在开发一个基于深度学习的图像分割模型&#xff0c;专门用于处理医学或遥感领域的图像数据&#xff08;以 TIFF 格式存储&#xff09;。通过结合 LeViT&#xff08;基于 Vision Transformer 的轻量模型&#xff09;和 U-Net 架构…

Java 17 新特性解析与代码示例

Java 17 新特性解析与代码示例 文章目录Java 17 新特性解析与代码示例引言1. 密封类&#xff08;JEP 409&#xff09;1.1. 介绍1.2. 详细说明1.3. 代码示例1.4. 与之前功能的对比1.5. 使用场景1.6. 总结2. switch 模式匹配&#xff08;预览&#xff0c;JEP 406&#xff09;2.1.…

SQL中的GROUP BY用法

GROUP BY 是 SQL 中用来“按列分组”的子句。 它把相同值的行分到同一个组&#xff0c;然后通常配合聚合函数&#xff08;COUNT, SUM, AVG, MAX, MIN 等&#xff09;对每个组做统计&#xff0c;最终每组只返回一行结果。✅ 1. 基本语法 SELECT 列1, 列2, 聚合函数(列3) FROM 表…

AI Agent开发学习系列 - LangGraph(10): 带有循环的Looping Graph(练习解答)

在AI Agent开发学习系列 - LangGraph(9): 带有循环的Looping Graph中&#xff0c;我们学习了如何创建带有循环的Looping Graph。为了巩固学习&#xff0c;我们来做一个练习。 用LangGraph创建如下图的一个Agent: 要求&#xff1a; 输入玩家姓名通过输入的上限值和下限值之间…

【保姆级 - 大模型应用开发】DeepSeek R1 本地部署全攻略:Ollama + vLLM + PyTorch 多选方案

DeepSeek R1 本地部署全攻略&#xff1a;Ollama vLLM PyTorch 多选方案 想部署 DeepSeek-R1 模型到本地&#xff0c;开启高性能推理体验&#xff1f;本文汇总了 Ollama、vLLM 及原生 PyTorch 的部署方法&#xff0c;适合不同开发者需求。 &#x1f3af; 下载模型 (必做) ----…