每次插入都要写
createTime = now()
?
修改都要手动设updateTime
?
用户信息还要到处传?
让 MyBatis-Plus 的 MetaObjectHandler
来接管这些重复逻辑
🐛 问题背景:公共字段的“重复赋值”问题
在大多数系统中,几乎每张表都有这些字段:
字段名 | 含义 | 赋值时机 |
---|---|---|
id | 主键(雪花算法) | 插入时 |
create_time | 创建时间 | 插入时 |
update_time | 更新时间 | 插入/更新时 |
create_by | 创建人 | 插入时 |
update_by | 更新人 | 更新时 |
delete_flag | 逻辑删除标志 | 插入时默认 false |
传统做法
order.setCreateTime(new Date());
order.setCreateBy(UserContext.getCurrentUser().getUsername());
order.setDeleteFlag(false);
orderService.save(order);
👉 问题来了:
- 每个接口都要写这些赋值逻辑,代码冗余
- 容易遗漏(比如忘了设
deleteFlag
)
解决方案:MyBatis-Plus MetaObjectHandler
统一处理
✅ 自定义元对象处理器
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
AuthUser authUser = UserContext.getCurrentUser();
String username = authUser != null ? authUser.getUsername() : "SYSTEM";
// 创建人
setFieldValByName("createBy", username, metaObject);
// 创建时间(仅当字段存在且为空时)
if (hasEmptyField(metaObject, "createTime")) {
setFieldValByName("createTime", new Date(), metaObject);
}
// 逻辑删除标志(默认 false)
if (hasEmptyField(metaObject, "deleteFlag")) {
setFieldValByName("deleteFlag", false, metaObject);
}
// 主键 ID(仅当未设置时)
if (hasEmptyField(metaObject, "id")) {
setFieldValByName("id", SnowFlake.getId(), metaObject); // 注意:返回 long
}
}
@Override
public void updateFill(MetaObject metaObject) {
AuthUser authUser = UserContext.getCurrentUser();
if (authUser != null) {
setFieldValByName("updateBy", authUser.getUsername(), metaObject);
}
// 更新时间(仅当字段存在时)
if (metaObject.hasGetter("updateTime")) {
setFieldValByName("updateTime", new Date(), metaObject);
}
}
/**
* 判断字段是否存在且值为空
*/
private boolean hasEmptyField(MetaObject metaObject, String fieldName) {
return metaObject.hasGetter(fieldName) && metaObject.getValue(fieldName) == null;
}
}
调用时只需:
Order order = new Order();
order.setOrderNo("NO20250902001");
order.setTotalAmount(new BigDecimal("999.00"));
orderService.save(order); // ⚡ 自动填充 id, createTime, createBy, deleteFlag
当然有些业务必须“提前知道 ID”【如生成订单操作,会创建订单记录和订单详情记录(绑定了orderId)】,hasEmptyField 更多是一种保底,建议在日常开发中手动给Id赋值
MetaObjectHandler
不仅消灭了重复代码,还让系统更规范、更健壮。
但记住:自动化不是万能的。
像订单这种“强关联”场景,需要提前生成 ID
参考: