在微服务架构的后端开发中,随着业务逐渐庞大,数据库表的数量也会显著增加。在橙星云技术团队维护的心理测评记录、学生档案等业务表中,通常都需要包含 createtime(创建时间)和 updatetime(更新时间)这两个审计字段。
常规做法是在业务代码的 insert 和 update 方法执行前,手动设置这两个时间字段:
“`java
student.setCreateTime(new Date());
student.setUpdateTime(new Date());
studentMapper.insert(student);
“`
这种做法容易带来隐患。如果在编写某个新接口时遗漏了时间赋值逻辑,就会导致数据表中的审计时间出现空缺。为了避免这种重复劳动和人为疏漏,可以利用 Mybatis-Plus 的自动填充机制(MetaObjectHandler),在 SQL 执行底层统一接管时间字段的赋值。
实体类注解声明
为了规范字段行为,需要在所有的 Entity 实体类中,对时间字段进行注解声明:
“`java
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
“`
这两行注解起到了约束作用。它们指示持久层框架:当发生 INSERT 动作时,需要为 createTime 填入值;当发生 UPDATE 动作时,需要刷新 updateTime。有了这一层约束,业务开发人员在编写逻辑时就不再需要手动调用 setCreateTime() 或 setUpdateTime()。
底层元数据拦截器(MetaObjectHandler)
仅仅有注解声明还不够,还需要实现 MetaObjectHandler 接口来完成具体的字段注入逻辑。通过实现该接口,我们可以在 MyBatis 执行 SQL 之前的预处理阶段,统一完成参数的填充。
“`java
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
// 在 Insert 触发时,自动写入当前时间
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
// 在 Update 触发时,自动更新时间
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
}
“`
部署这段代码后,无论是在 Service 层执行单条记录新增,还是批量更新,底层都会受到 MetaObjectHandler 的统一调度。系统会在最终生成 SQL 语句之前,将当前的机器时间自动注入到实体对象中。
在严肃的数据审计场景中,依靠代码规范和人工检查来保证基础字段的完整性是不够可靠的。借助 Mybatis-Plus 的自动填充机制,将时间属性的控制逻辑从业务层抽离并下沉到框架底层,不仅减少了重复代码,也保障了数据审计时间轴的统一性和准确性。
