目录
[🌰 举个直观例子](#🌰 举个直观例子)
[🛠️ 核心作用原理](#🛠️ 核心作用原理)
[📜 代码级工作流程](#📜 代码级工作流程)
[📜 完整代码](#📜 完整代码)
[🔍 关键概念拆解](#🔍 关键概念拆解)
[⚠️ 常见问题排查](#⚠️ 常见问题排查)
[🌟 设计意义](#🌟 设计意义)
🌰 举个直观例子
package work.dduo.ans.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Date;
/**
*
* @TableName t_visit_log
*/
@TableName(value ="t_visit_log")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TVisitLog implements Serializable {
/**
* id
*/
@TableId(type = IdType.AUTO)
private Integer id;
/**
* 访问ip
*/
private String ipAddress;
/**
* 访问地址
*/
private String ipSource;
/**
* 操作系统
*/
private String os;
/**
* 访问时间
* 使用mybatis-plus的元对象处理器自动填充
*/
@TableField(fill=FieldFill.INSERT)
private Date createTime;
private static final long serialVersionUID = 1L;
}
假设你每次保存订单时都要记录 "订单创建时间":
- 没有元对象处理器 :每次插入数据都要手动写
order.setCreateTime(new Date())
- 有了元对象处理器:你只需专注业务逻辑,框架自动帮你填充这个时间
🛠️ 核心作用原理
- 拦截数据库操作
MyBatis-Plus 在执行insert()
或update()
操作时,会触发元对象处理器。 - 通过注解识别目标字段
字段上的@TableField(fill = FieldFill.INSERT)
注解会告诉处理器:"这个字段需要自动填充"。 - 反射动态赋值
处理器利用反射机制,通过MetaObject
对象直接操作实体类的字段值(无需手动调用 set 方法)。
📜 代码级工作流程
以你的 createTime
字段为例:
// 1. 你的实体类标记了自动填充
public class TVisitLog {
@TableField(fill = FieldFill.INSERT)
private Date createTime;
}
// 2. 插入操作时自动触发
TVisitLog log = new TVisitLog();
visitLogMapper.insert(log); // ← 这里自动填充 createTime
// 3. 处理器内部执行(伪代码)
class MyMetaObjectHandler {
void insertFill() {
if (字段有 @TableField(fill=INSERT)) {
用反射给字段赋值 new Date()
}
}
}
📜 完整代码
package work.dduo.ans.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
}
}
🔍 关键概念拆解
|----------------------|------------------------------------------|
| 概念 | 说明 |
| MetaObject | 对实体类的动态包装器,提供反射操作字段的能力(类似一个能透视对象内部结构的工具) |
| FieldFill | 填充策略枚举,包含 INSERT(插入时填充)、UPDATE(更新时填充)等 |
| strictInsertFill | 严格模式填充方法,确保字段存在且类型匹配 |
⚠️ 常见问题排查
如果自动填充失效,检查:
- 处理器类是否添加了
@Component
注解 - 实体类字段名与处理器中写的名称是否完全一致(包括大小写)
- 是否在主启动类的扫描范围内(位于同一包或子包)
- 数据库字段是否有默认值冲突(建议同时设置数据库默认值
CURRENT_TIMESTAMP
)
🌟 设计意义
通过元对象处理器,实现了:
✅ 业务代码与非业务逻辑解耦 (时间记录等通用操作集中管理)
✅ 消除重复代码 (避免每个插入操作都写 setCreateTime)
✅ 保证数据一致性(比如强制所有表统一使用同一时间生成规则)