MyBatis MetaObjectHandler: 优雅地统一处理实体类字段

  在现代 Web 应用开发中,我们经常需要在数据库表中记录数据的创建时间、创建者、更新时间和更新者信息,这些字段(通常是 createTime、createBy、updateTime 和 updateBy)在很多实体类中都需要存在。如果每次都手动设置这些字段,不仅会产生大量的重复代码,还会降低开发效率,更可能导致数据不一致。MyBatis 提供了一个强大的接口 MetaObjectHandler,可以帮助我们优雅地统一处理这些字段,让代码更加简洁、易维护。
  本文将深入探讨如何使用 MyBatis 的 MetaObjectHandler 来自动填充实体类的 createTime、createBy、updateTime 和 updateBy 字段,并提供完整的代码示例和最佳实践。

一、为什么需要 MetaObjectHandler?

  1. 避免重复代码: 无需在每个 Service 或 Controller 中重复编写字段填充代码,减少代码冗余。
  2. 提高开发效率:只需专注于业务逻辑,无需关注这些通用字段,提高开发效率。
  3. 确保数据一致性: 通过统一的处理逻辑,确保 create 和 update数据的一致性。
  4. 方便数据审计: 统一处理这些字段,方便数据审计和追溯。
  5. 代码简洁:将字段处理逻辑集中到一个地方,提高代码的可读性和可维护性。

二、MyBatis MetaObjectHandler 原理

  MetaObjectHandler 是 MyBatis 提供的一个接口,它允许我们在 MyBatis 执行 SQL 语句之前或之后拦截并修改元对象(MetaObject)的属性。 MetaObject 封装了实体对象,我们可以通过 MetaObject 来访问和修改实体类的字段值。MetaObjectHandler 提供了两个关键方法:

  1. insertFill(MetaObject metaObject): 在执行 INSERT 语句之前调用,用于填充新增数据时的字段。
  2. updateFill(MetaObject metaObject): 在执行 UPDATE 语句之前调用,用于填充更新数据时的字段。

三、实践:使用 MetaObjectHandler 自动填充字段

3.1 创建公共实体类(BaseEntity)

@Data
public class BaseEntity<T> extends Model {

    /**
     * 创建人
     */
    @ApiModelProperty(value = "创建人")
    @TableField(value = "create_by", fill = FieldFill.INSERT)
    private String createBy;

    /**
     * 创建时间
     */
    @ApiModelProperty(value = "创建时间")
    @TableField(value = "create_time", fill = FieldFill.INSERT)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime createTime;

    /**
     * 更新人
     */
    @ApiModelProperty(value = "更新人")
    @TableField(value = "update_by", fill = FieldFill.INSERT_UPDATE)
    private String updateBy;

    /**
     * 更新时间
     */
    @ApiModelProperty(value = "更新时间")
    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime updateTime;

    /**
     * 备注
     */
    @ApiModelProperty(value = "备注")
    @TableField(value = "remark")
    private String remark;
}

3.2 创建 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 MybatisMetaObjectHandler implements MetaObjectHandler {

    /**
     * 新增时填充创建人和创建时间
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createBy", String.class, getUsername());
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
    }

    /**
     * 更新时填充更新人和更新时间
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "updateBy", String.class, getUsername());
        this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
    }
	
	private String getUsername() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated()) {
            return "system"; // 默认值
        }
        return authentication.getName();
    }
}
  1. insertFill 方法:设置 createTime、createBy的值。
  2. updateFill 方法:设置 updateTime 和updateBy 的值。
  3. strictInsertFillstrictUpdateFill 方法:是 MyBatis Plus 提供的便利方法,会自动处理类型转换和字段存在性检查。
  4. getUsername 方法: 从 Spring Security 的上下文中获取用户名,如果没取到则使用默认值,需要根据实际情况修改。

3.3 创建数据库表

CREATE TABLE `t_user` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `user_name` varchar(255) DEFAULT NULL COMMENT '用户名称',
  `user_desc` varchar(255) DEFAULT NULL COMMENT '用户描述',
  `create_by` varchar(64) NOT NULL COMMENT '创建人',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_by` varchar(64) DEFAULT NULL COMMENT '更新人',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  `remark` varchar(500) DEFAULT NULL COMMENT '备注'
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3

3.4 使用生成的实体类继承BaseEntity

public class User extends BaseEntity<User> {

    private static final long serialVersionUID = 1L;

    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
	
    @TableField("user_name")
    private String userName;

    @TableField("user_desc")
    private String userDesc;

    @Override
    public Serializable pkVal() {
        return this.id;
    }
}

现在,你可以调用 insert 和 update 操作,MetaObjectHandler 将会自动设置这些字段的值,无需任何额外处理。

四、注意事项

  1. 字段类型一致性: 确保实体类中字段的类型和 MetaObjectHandler 中设置的类型一致,避免类型转换错误。
  2. 获取用户信息getUsername 方法需要根据你的实际应用场景进行修改,可以从 Spring Security上下文、Token 或其他地方获取当前用户信息。
  3. 配合Mybatis Plus使用: 以上代码使用的是 mybatis plus 的MetaObjectHandler
  4. 数据库表字段: 数据库表字段设置 createTimecreateBy不能更新, 并设置默认值。
  5. 更新操作:update 操作的时候可能会生成不了update_by和update_time,注意更新语句的写法。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LDD3学习9--数据类型和定时器

这部分对应的是第七章和第十一章&#xff0c;因为内容也不是很多&#xff0c;就一起写了。里面的内容基本上就是一个个的点&#xff0c;所以也就一个个点简单总结一下。 1 数据类型 1.1 数据长度 不同操作系统类型长度可能不一样&#xff0c;看图的话最好用u8&#xff0c;u16&…

python http server运行Angular 单页面路由时重定向,解决404问题

问题 当Angular在本地ng server运行时候&#xff0c;可以顺利访问各级路由。 但是运行ng build后&#xff0c;在dist 路径下的打包好的额index.html 必须要在服务器下运行才能加载。 在服务器下我们第一次访问路由页面时是没有问题的&#xff0c;但是尝试刷新页面或手动输入路…

SparkSQL数据源与数据存储

文章目录 1. 大数据分析流程2. Spark SQL数据源2.1 SparkSQL常见数据源2.2 SparkSQL支持的文本格式2.3 加载外部数据源步骤 3. 本地文件系统加载数据3.1 本地文件系统加载JSON格式数据3.1.1 概述3.1.2 案例演示 3.2 本地文件系统加载CSV格式数据3.2.1 概述3.2.2 案例演示 3.3 本…

LLM - 大模型 ScallingLaws 的 CLM 和 MLM 中不同系数(PLM) 教程(2)

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/145188660 免责声明&#xff1a;本文来源于个人知识与公开资料&#xff0c;仅用于学术交流&#xff0c;欢迎讨论&#xff0c;不支持转载。 Scalin…

AI agent 在 6G 网络应用,无人机群控场景

AI agent 在 6G 网络应用,无人机群控场景 随着 6G 时代的临近,融合人工智能成为关键趋势。借鉴 IT 行业 AI Agent 应用范式,提出 6G AI Agent 技术框架,包含多模型融合、定制化 Agent 和插件式环境交互理念,构建了涵盖四层结构的框架。通过各层协同实现自主环境感知等能力…

信息奥赛一本通 1168:大整数加法

这道题是一道大整数加法&#xff0c;涉及到高精度的算法&#xff0c;比如说有两个数要进行相加&#xff0c;1111111111111111111111111111111111111112222222222222222222222222222222&#xff0c;那么如果这两个数很大的话我们常用的数据类型是不能进行计算的&#xff0c;那么…

基于YOLOv4与Tkinter的口罩识别系统

往期精彩 基于YOLOv11的番茄成熟度实时检测系统设计与实现 用YOLOv11检测美国手语&#xff1a;挥动手腕的科技魔法 基于YOLOv11模型PyQt的实时鸡行为检测系统研究 OpenCV与YOLO在人脸识别中的应用研究(论文源码) 计算机视觉&#xff1a;农作物病虫害检测系统&#xff1a;基于Y…

机器学习:监督学习与非监督学习

监督学习是利用带有标签的数据进行训练,模型通过学习输入和输出之间的关系来进行预测。也就是说,数据集中既有输入特征,也有对应的输出标签,模型的目标是找到从输入到输出的映射关系。 而无监督学习则使用没有标签的数据进行训练,模型的任务是发现数据中的内在结构或模式…

【unity进阶篇】不同Unity版本对应的C# 版本和API 兼容级别(Api Compatibility Level)选择

考虑到每个人基础可能不一样&#xff0c;且并不是所有人都有同时做2D、3D开发的需求&#xff0c;所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】&#xff1a;主要讲解C#的基础语法&#xff0c;包括变量、数据类型、运算符、…

H3CNE-13-静态路由(二)

1.路由优先级 路由类型DirectOSPFStaticRIP管理距离01060100 2.路由度量 配置示例&#xff1a; 配置接口IP、静态路由&#xff08;去包、回包&#xff09; 3.静态路由之路由备份 RTB: ip route-static 192.168.1.0 24 10.0.12.1 ip route-ststic 192.168.1.0 24 20.0.12.1 …

【数据分享】1929-2024年全球站点的逐年平均气温数据(Shp\Excel\无需转发)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、湿度等指标&#xff0c;其中又以气温指标最为常用&#xff01;说到气温数据&#xff0c;最详细的气温数据是具体到气象监测站点的气温数据&#xff01;本次我们为大家带来的就是具体到气象监…

[Qualcomm]Qualcomm MDM9607 SDK代码下载操作说明

登录Qualcomm CreatePoing Qualcomm CreatePointhttps://createpoint.qti.qua

PID控制算法原理,并用python实现演示

PID算法控制运用在哪些地方&#xff1f; PID&#xff1a;比列(Proportion)&#xff0c;积分(Integral)&#xff0c;微分(Differential) PID算法可以用来控制温度&#xff0c;压强&#xff0c;流量&#xff0c;化学成分&#xff0c;速度等等。汽车的定速巡航&#xff1b;伺服驱…

C语言之文本加密程序设计

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 文本加密程序设计 摘要&#xff1a;本文设计了一种文本加密程序&#xff0c;旨在提高信息安…

数字图像处理:实验二

任务一&#xff1a; 将不同像素&#xff08;32、64和256&#xff09;的原图像放大为像素大 小为1024*1024的图像&#xff08;图像自选&#xff09; 要求&#xff1a;1&#xff09;输出一幅图&#xff0c;该图包含六幅子图&#xff0c;第一排是原图&#xff0c;第 二排是对应放大…

latin1_swedish_ci(latin1 不支持存储中文、日文、韩文等多字节字符)

文章目录 1、SHOW TABLE STATUS WHERE Name batch_version;2、latin1_swedish_ci使用场景注意事项修改字符集和排序规则修改表的字符集和排序规则修改列的字符集和排序规则修改数据库的默认字符集和排序规则 3、ALTER TABLE batch_version CONVERT TO CHARACTER SET utf8mb4 C…

基于微信小程序的安心陪诊管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

如何将自己本地项目开源到github上?

环境&#xff1a; LLMB项目 问题描述&#xff1a; 如何将自己本地项目开源到github上&#xff1f; 解决方案&#xff1a; 步骤 1: 准备本地项目 确保项目整洁 确认所有的文件都在合适的位置&#xff0c;并且项目的 README.md 文件已经完善。检查是否有敏感信息&#xff0…

CSS笔记01

黑马程序员视频地址&#xff1a; 前端Web开发HTML5CSS3移动web视频教程https://www.bilibili.com/video/BV1kM4y127Li?vd_source0a2d366696f87e241adc64419bf12cab&spm_id_from333.788.videopod.episodes 目录 引入方式 CSS特性 继承性 层叠性 优先级 Emmet写法 …

【机器学习】制造业转型:机器学习如何推动工业 4.0 的深度发展

我的个人主页 我的领域&#xff1a;人工智能篇&#xff0c;希望能帮助到大家&#xff01;&#xff01;&#xff01;&#x1f44d;点赞 收藏❤ 引言 在当今科技飞速发展的时代&#xff0c;制造业正经历着前所未有的变革&#xff0c;工业4.0的浪潮席卷而来。工业4.0旨在通过将…