MySQL自动填充时间的两种方式:数据库与MyBatis-Plus实战
在关系型数据库开发中,自动维护数据的创建时间与更新时间是常见需求。本文详细解析通过 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 高级特性的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













