MySQL自动填充时间的两种方式:数据库与MyBatis-Plus实战

Theo
Theo
发布时间:2026-10-15 | 4人浏览过
原创

在关系型数据库开发中,自动维护数据的创建时间与更新时间是常见需求。本文详细解析通过 MySQL DDL 原生特性以及 Java 框架 MyBatis-Plus 的 MetaObjectHandler 实现自动填充时间的方法。

实现目标

我们需要在数据表(例如 users)中维护两个时间字段:create_time 表示记录创建时的绝对时间,update_time 表示最后修改记录的时间。期望达到的效果是:

  • INSERT(新增)时: create_time 和 update_time 同时被赋予当前系统时间。
  • UPDATE(修改)时: 仅 update_time 自动更新至当前系统时间,create_time 保持不变。

准备条件

  • 数据库环境: MySQL 5.6 及以上版本(5.6+ 开始支持 CURRENT_TIMESTAMP 对多个字段的更灵活控制)。
  • 开发工具: MySQL Workbench / Navicat 等可视化工具,或命令行客户端。
  • 框架依赖: 如果使用代码方案,需确保项目中已集成 MyBatis-Plus 且引入了 Lombok。

方法一:使用数据库原生 DDL(数据库级别)

这是最底层的实现方式,无需任何代码侵入,完全由数据库引擎负责时间维护。

第1步:设计数据表结构

新建或修改表时,在 SQL 定义中直接为字段指定默认值和 onUpdate 动作。

CREATE TABLE `your_table` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

关键点说明:

  • DEFAULT CURRENT_TIMESTAMP:告诉数据库在新建记录若无显式赋值,则填入当前时间。
  • ON UPDATE CURRENT_TIMESTAMP:当执行 update 语句时,若未显式赋值该字段,数据库会自动刷新为当前时间。


第2步:处理实体类同步

如果项目使用了 ORM(如 Hibernate、JPA 或纯 JDBC),需要在对应的 Java 实体类中声明这两个字段,以便后续查询和传输。

注:由于该方法强依赖数据库权限,在实际团队协作或生产环境中,普通开发人员通常无权直接修改 DDL,因此工程上更多采用以下“方法二”。

方法二:基于 MyBatis-Plus 代码级自动填充

将时间维护逻辑从数据库剥离,交由应用层控制。这种方式更加灵活,且不占用数据库资源,也解决了多人协作时的表结构变更权限问题。

第1步:清理数据库约束

为了保证不冲突,首先应当移除数据库层面的自动触发机制。如果之前有 ON UPDATE CURRENT_TIMESTAMP,请使用 ALTER TABLE 删除它。此时,字段在数据库中的默认值可以为空或保持普通默认值,不再承担自动刷新的职责。


第2步:实体类增加填充标识注解

在实体类需要自动填充的字段上加 @TableField(fill = ...) 注解。

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import java.util.Date;

public class User {
    @TableId(type = IdType.AUTO)
    private Long id;
    
    // 仅在 INSERT 时填充
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    
    // 在 INSERT 和 UPDATE 时均填充
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
}

第3步:编写自动填充策略处理器

创建一个实现了 MetaObjectHandler 接口的 Bean,Spring 扫描到后会将其注册到 IOC 容器中。

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;

@Slf4j
@Component // 必须交给 Spring 管理
public class MyMetaObjectHandler implements MetaObjectHandler {

    /**
     * 插入时的填充策略
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill.....");
        this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
        this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
    }

    /**
     * 更新时的填充策略
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill.....");
        // 注意:更新时只更新 updateTime,不要覆盖 createTime
        this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
    }
}

技术要点:

  • strictInsertFill 和 strictUpdateFill 是较新版本的 MP API,能更安全地判断字段是否为空再进行填充。
  • 注入 log 有助于在测试阶段确认处理器是否真的被触发。

第4步:运行验证测试

执行一次保存操作(Save/Insert),检查数据库返回的记录中 createTime 和 updateTime 是否一致且正确。

随后执行一次修改操作(Update),仅更改非时间字段,再次查看 updateTime 是否刷新,而 createTime 依然保留最初的值。

简要总结

MySQL 原生的 CURRENT_TIMESTAMP 适合个人单点部署项目,零配置但缺乏灵活性;而在团队开发和微服务架构中,推荐使用 MyBatis-Plus 结合 MetaObjectHandler 的方案,不仅能解耦业务逻辑与存储引擎,还能轻松扩展逻辑(例如在填充时间时同时填充修改人 ID)。

以上就是 MySQL 自动填充时间的详细内容,更多关于 SQL 高级特性的资料请关注本站其它相关文章!

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表