MyBatis与MyBatis-Plus:字段自动填充的两种实现方式

news2025/4/22 9:29:28

目录

1. 使用 MyBatis 拦截器实现字段自动填充

2. 使用 MyBatis-Plus 实现字段自动填充


1. 使用 MyBatis 拦截器实现字段自动填充

实现步骤
  1. 创建拦截器 实现 MyBatis 的 Interceptor 接口,通过拦截 MyBatis 执行的 SQL 操作来自动填充公共字段

    @Intercepts({
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
    })
    public class CommonFieldInterceptor implements Interceptor {
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            if (invocation.getArgs().length > 1) {
                Object parameter = invocation.getArgs()[1];
                if (parameter instanceof BaseEntity) {
                    BaseEntity entity = (BaseEntity) parameter;
                    if (isInsertOperation(invocation)) {
                        entity.setCreateTime(new Date());
                        entity.setUpdateTime(new Date());
                    } else if (isUpdateOperation(invocation)) {
                        entity.setUpdateTime(new Date());
                    }
                }
            }
            return invocation.proceed();
        }
    
        private boolean isInsertOperation(Invocation invocation) {
            String methodName = ((MappedStatement) invocation.getArgs()[0]).getId();
            return methodName.contains("insert");
        }
    
        private boolean isUpdateOperation(Invocation invocation) {
            String methodName = ((MappedStatement) invocation.getArgs()[0]).getId();
            return methodName.contains("update");
        }
    
        @Override
        public Object plugin(Object target) {
            return Plugin.wrap(target, this);
        }
    
        @Override
        public void setProperties(Properties properties) {
            // 可选:设置属性
        }
    }
  2. 定义基础实体类 创建一个基础实体类 BaseEntity,包含需要自动填充的公共字段,所有需要自动填充的实体类都应继承该类

    public class BaseEntity {
        private Date createTime;
        private Date updateTime;
    
        // getters and setters
        public Date getCreateTime() {
            return createTime;
        }
    
        public void setCreateTime(Date createTime) {
            this.createTime = createTime;
        }
    
        public Date getUpdateTime() {
            return updateTime;
        }
    
        public void setUpdateTime(Date updateTime) {
            this.updateTime = updateTime;
        }
    }
  3. 配置拦截器 在 MyBatis 配置文件中注册拦截器

    <plugins>
        <plugin interceptor="com.example.mybatis.interceptor.CommonFieldInterceptor"/>
    </plugins>
  4. 使用示例 创建一个继承 BaseEntity 的实体类,并在 Mapper 中使用该实体类进行数据库操作

    public class User extends BaseEntity {
        private Long id;
        private String name;
    
        // getters and setters
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    @Mapper
    public interface UserMapper {
        @Insert("INSERT INTO user (name, create_time, update_time) VALUES (#{name}, #{createTime}, #{updateTime})")
        void insert(User user);
    
        @Update("UPDATE user SET name = #{name}, update_time = #{updateTime} WHERE id = #{id}")
        void update(User user);
    }

2. 使用 MyBatis-Plus 实现字段自动填充

实现步骤
  1. 定义实体类 在实体类中,使用 @TableField 注解来标记需要自动填充的字段,并指定填充策略

    @Data
    @TableName("user")
    public class User {
        @TableId(type = IdType.AUTO)
        private Integer id;
    
        private String username;
    
        @TableField(fill = FieldFill.INSERT)
        private LocalDateTime createdAt;  // 创建时自动填充
    
        @TableField(fill = FieldFill.INSERT_UPDATE)
        private LocalDateTime updatedAt;  // 创建和更新时自动填充
    }
  2. 实现 MetaObjectHandler 创建一个类实现 MetaObjectHandler 接口,并重写 insertFillupdateFill 方法,定义插入和更新时的填充逻辑。

    @Component
    public class MyMetaObjectHandler implements MetaObjectHandler {
        @Override
        public void insertFill(MetaObject metaObject) {
            this.strictInsertFill(metaObject, "createdAt", LocalDateTime::now, LocalDateTime.class);
            this.strictInsertFill(metaObject, "updatedAt", LocalDateTime::now, LocalDateTime.class);
        }
    
        @Override
        public void updateFill(MetaObject metaObject) {
            this.strictUpdateFill(metaObject, "updatedAt", LocalDateTime::now, LocalDateTime.class);
        }
    }
  3. 配置自动填充处理器 确保 MyMetaObjectHandler 类被 Spring 管理,可以通过 @Component@Bean 注解来实现。

  4. 使用示例 创建一个继承自 BaseMapper 的 Mapper 接口

    @Mapper
    public interface UserMapper extends BaseMapper<User> {
    }

    测试代码

    @Component
    public class MyTestRunner implements CommandLineRunner {
        @Autowired
        private UserMapper userMapper;
    
        @Override
        public void run(String... args) throws Exception {
            // 测试插入时自动填充
            User user = new User();
            user.setUsername("John Doe");
            userMapper.insert(user);
            System.out.println("Inserted user: " + user);
    
            // 测试更新时自动填充
            user.setUsername("Jane Doe");
            userMapper.updateById(user);
            System.out.println("Updated user: " + user);
        }
    }

两种方式的对比

  • MyBatis 拦截器方式

    • 优点:灵活性高,可以自定义复杂的填充逻辑,适用于复杂的业务场景。

    • 缺点:实现相对复杂,需要编写较多代码,且需要手动添加注解。

  • MyBatis-Plus 方式

    • 优点:使用简单,代码量少,开箱即用,与 MyBatis-Plus 无缝集成。

    • 缺点:填充逻辑相对固定,扩展性较差。

选择建议

  • 如果需要实现简单的自动填充功能,如创建时间和更新时间的自动填充,推荐使用 MyBatis-Plus 方式

  • 如果有复杂的业务逻辑,需要自定义填充逻辑,推荐使用 MyBatis 拦截器方式

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

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

相关文章

在Qt中验证LDAP账户(Windows平台)

一、前言 原本以为在Qt&#xff08;Windows平台&#xff09;中验证 LDAP 账户很简单&#xff1a;集成Open LDAP的开发库即可。结果临了才发现&#xff0c;Open LDAP压根儿不支持Windows平台。沿着重用的原则&#xff0c;考虑迁移Open LDAP的源代码&#xff0c;却发现工作量不小…

【sylar-webserver】重构日志系统

文章目录 主要工作流程图FiberConditionBufferBufferManagerLogEvent 序列化 & 反序列化LoggerRotatingFileLogAppender 主要工作 实现&#xff0c; LogEvent 序列化和反序列化 &#xff08;使用序列化是为了更标准&#xff0c;如果转成最终的日志格式再存储&#xff08;确…

树莓派超全系列教程文档--(38)config.txt视频配置

config.txt视频配置 视频选项HDMI模式树莓派4-系列的HDMI树莓派5-系列的HDMI 复合视频模式enable_tvout LCD显示器和触摸屏ignore_lcddisable_touchscreen 通用显示选项disable_fw_kms_setup 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 视频选…

线性DP:最短编辑距离

Dp 状态表示 f&#xff08;i&#xff0c;j&#xff09; 集合所有将A[1~i]变成B[1~j]的操作方式属性min 状态计算 &#xff08;划分&#xff09; 增f(i,j)f(i,j-1)1//A[i]元素要增加&#xff0c;说明A前i位置与B前j-1相同删f(i,j)f(i-1,j)1//A[i]元素要删除&#xff0c;说明A前i…

STM32——新建工程并使用寄存器以及库函数进行点灯

本文是根据江协科技提供的教学视频所写&#xff0c;旨在便于日后复习&#xff0c;同时供学习嵌入式的朋友们参考&#xff0c;文中涉及到的所有资料也均来源于江协科技&#xff08;资料下载&#xff09;。 新建工程并使用寄存器以及库函数进行点灯操作 新建工程步骤1.建立工程2.…

java集合框架day1————集合体系介绍

在进入正文之前&#xff0c;我们先来思考一下之前学过的数组有什么缺点&#xff1f; <1>长度开始时必须指定&#xff0c;而且一旦指定&#xff0c;不能更改 <2>保存的必须为同一类型的元素 <3>使用数组进行增加/删除元素的代码比较麻烦 为了方便读者理解&…

百度热力图数据获取,原理,处理及论文应用18

目录 0、数据简介0、示例数据1、百度热力图数据日期如何选择1.1、其他实验数据的时间1.2、看日历天气 2、百度热力图几天够研究&#xff1f;部分文章统计3、数据原理3.1 Bd09mc即百度墨卡托投影坐标系200单位的距离是可以自己设置的吗&#xff1f;3.2 csv文件字段说明3.3 ** 这…

【身份证扫描件识别表格】如何识别大量身份证扫描件将内容导出保存到Excel表格,一次性处理多张身份证图片导出Excel表格,基于WPF和腾讯云的实现方案

基于WPF和腾讯云的身份证扫描件批量处理方案 适用场景 本方案适用于需要批量处理大量身份证扫描件的场景,例如: 企业人事部门批量录入新员工身份信息银行或金融机构办理批量开户业务教育机构收集学生身份信息政府部门进行人口信息统计酒店、医院等需要实名登记的场所这些场景…

基于语义网络表示的不确定性推理

前文我们已经了解了: 1.不确定与非单调推理的基本概念:不确定与非单调推理的基本概念-CSDN博客 2.不确定与非单调推理的概率方法:不确定与非单调推理的概率方法-CSDN博客 3.不确定与非单调推理的可信度方法:不确定与非单调推理的可信度方法-CSDN博客 4.不确定与非单调推…

ICMAN防水触摸芯片 - 复杂环境下精准交互,提升触控体验

▍核心优势 ◆ 超强抗干扰能力 ◆ 工业级设计&#xff0c;一致性和稳定性好 ▍提供场景化解决方案 【智能厨电矩阵】抽油烟机档位调节 | 电磁炉火力触控 | 洗碗机模式切换 【卫浴设备方案】淋浴房雾化玻璃控制 | 智能马桶触控面板 | 浴缸水位感应 【工业控制应用】仪器仪…

【java实现+4种变体完整例子】排序算法中【希尔排序】的详细解析,包含基础实现、常见变体的完整代码示例,以及各变体的对比表格

以下是希尔排序的详细解析&#xff0c;包含基础实现、常见变体的完整代码示例&#xff0c;以及各变体的对比表格&#xff1a; 一、希尔排序基础实现 原理 希尔排序是插入排序的改进版本&#xff0c;通过分步缩小增量间隔&#xff0c;将数组分成多个子序列进行插入排序&#…

matlab 处理海洋数据并画图的工具包--ocean_data_tools

matlab 处理海洋数据并画图的工具包–ocean_data_tools matlab 处理海洋数据并画图的工具包–ocean_data_tools ocean_data_tools 简化了提取、格式化和可视化免费可用的海洋学数据的过程。虽然可以在线访问大量海洋学数据&#xff0c;但由于获取这些数据并将其格式化为可用数据…

MCP:AI时代的“万能插座”,开启大模型无限可能

摘要&#xff1a;Model Context Protocol&#xff08;MCP&#xff09;由Anthropic在2024年底开源&#xff0c;旨在统一大模型与外部工具、数据源的通信标准。采用客户端-服务器架构&#xff0c;基于JSON-RPC 2.0协议&#xff0c;支持stdio、SSE、Streamable HTTP等多种通信方式…

静态网页的开发

文章目录 基于 idea 开发静态网页添加web框架前端配置服务器并启动服务资源名字不是 index 静态网页 流转 基于 idea 开发静态网页 添加web框架 方法1 方法2 前端 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8&quo…

【CPU】结合RISC-V CPU架构回答中断系统的7个问题(个人草稿)

结合RISC-V CPU架构对中断系统七个关键问题的详细解析&#xff0c;按照由浅入深的结构进行说明&#xff1a; 一、中断请求机制&#xff08;问题①&#xff09; 硬件基础&#xff1a; RISC-V通过CLINT&#xff08;Core Local Interrupter&#xff09;和PLIC&#xff08;Platfor…

uCOS3实时操作系统(任务切换和任务API函数)

文章目录 任务切换任务API函数 任务切换 C/OS-III 将 PendSV 的中断优先级配置为最低的中断优先级&#xff0c;这么一来&#xff0c; PendSV 异常的中断服务函数就会在其他所有中断处理完成后才被执行。C/OS-III 就是将任务切换的过程放到 PendSV 异常的中断服务函数中处理的。…

科学养生指南:解锁健康生活新方式

在快节奏的现代生活中&#xff0c;健康养生已成为人们关注的焦点。科学合理的养生方式&#xff0c;能帮助我们增强体质、预防疾病&#xff0c;享受更优质的生活。​ 饮食是健康养生的基石。遵循 “均衡饮食” 原则&#xff0c;每日饮食需包含谷类、蔬菜水果、优质蛋白质和健康…

第十四届蓝桥杯 2023 C/C++组 有奖问答

目录 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 思路&#xff1a; 核心思路&#xff1a; 思路详解&#xff1a; 代码&#xff1a; 代码详解&#xff1a; 题目&#xff1a; 题目描述&#xff1a; 题目链接&#xff1a; 蓝桥云课 有奖问答 思路&…

transformer注意力机制

单头注意力机制 import torch import torch.nn.functional as Fdef scaled_dot_product_attention(Q, K, V):# Q: (batch_size, seq_len, d_k)# K: (batch_size, seq_len, d_k)# V: (batch_size, seq_len, d_v)batch_size: 一次输入的句子数。 seq_len: 每个句子的词数。 d_mo…

QT 5.15 程序打包

说明&#xff1a; windeployqt 是 Qt 提供的一个工具&#xff0c;用于自动收集并复制运行 Qt 应用程序所需的动态链接库&#xff08;.dll 文件&#xff09;及其他资源&#xff08;如插件、QML 模块等&#xff09;到可执行文件所在的目录。这样你就可以将应用程序和这些依赖项一…