MyBatis-Plus 自动填充用于统一处理数据库通用字段的赋值,无需在业务代码中手动设置,大幅简化开发:
通用字段:创建人ID、创建时间、更新人ID、更新时间
核心优势:无侵入、统一维护、避免重复代码、保证数据规范
基于 MetaObjectHandler 接口实现,MyBatis-Plus 拦截 insert/update 操作
通过 @TableField(fill = 策略) 标记需要填充的字段
自定义处理器实现插入 / 更新时的自动赋值逻辑
底层通过元对象 MetaObject 操作实体属性,无反射安全风险
CREATE TABLE `user` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`create_user_id` bigint DEFAULT NULL COMMENT '创建人ID',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_user_id` bigint DEFAULT NULL COMMENT '更新人ID',
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;企业级最佳实践
抽取通用基类(复用字段,推荐)
所有实体继承该基类,无需重复定义通用字段
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class BaseEntity {
// 插入时填充
@TableField(fill = FieldFill.INSERT)
private Long createUserId;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
// 插入+更新时填充
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUserId;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
}实体类继承基类
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class User extends BaseEntity {
private String name;
}实现自动填充处理器(核心)
修正原代码错误:更新操作必须用 strictUpdateFill,支持动态获取登录用户 ID(非写死)
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
/**
* 自动填充配置类,必须交给Spring管理
*/
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* 插入数据时填充
*/
@Override
public void insertFill(MetaObject metaObject) {
log.info("【自动填充】执行插入填充...");
// 1. 填充创建/更新人(实际业务从上下文获取登录用户ID)
Long userId = getCurrentUserId();
// 2. 严格填充:字段类型匹配、注解策略匹配才赋值
this.strictInsertFill(metaObject, "createUserId", Long.class, userId);
this.strictInsertFill(metaObject, "updateUserId", Long.class, userId);
// 3. 填充时间
this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
/**
* 更新数据时填充
*/
@Override
public void updateFill(MetaObject metaObject) {
log.info("【自动填充】执行更新填充...");
Long userId = getCurrentUserId();
// 更新操作必须使用 strictUpdateFill
this.strictUpdateFill(metaObject, "updateUserId", Long.class, userId);
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
}
/**
* 模拟:获取当前登录用户ID
* 实际项目:从SpringSecurity、ThreadLocal、Token中获取
*/
private Long getCurrentUserId() {
// 示例:默认1L,替换为真实业务逻辑
return 1L;
}
}// 插入严格填充
this.strictInsertFill(元对象, 字段名, 字段类型, 填充值);
// 更新严格填充
this.strictUpdateFill(元对象, 字段名, 字段类型, 填充值);规则:
必须匹配 @TableField(fill = 策略)
必须匹配字段类型
字段已有值 → 不覆盖
填充值为 null → 不填充
无策略校验
无视 FieldFill 注解,直接赋值,适用于自定义场景:
this.fillStrategy(metaObject, "updateTime", LocalDateTime.now());高级
无视原有值,强制赋值
this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);public enum FieldFill {
DEFAULT, // 默认:不填充
INSERT, // 仅插入时填充
UPDATE, // 仅更新时填充
INSERT_UPDATE // 插入+更新时都填充(更新人/时间专用)
}baseMapper.insert(entity)
baseMapper.updateById(entity)
baseMapper.update(entity, wrapper)
批量插入 / 更新(MP 批量方法)
方法参数实体名为 et(默认规则)
更新时 entity 为 null:update(null, wrapper) → 不填充
自定义 Mapper 方法参数名不是 et:
// 失效
updateXXX(@Param("user") User user);
// 生效
updateXXX(@Param("et") User user);处理器未加 @Component(未被 Spring 管理)
字段类型不匹配(如实体用 String,填充用 LocalDateTime)
@SpringBootTest
public class AutoFillTest {
@Autowired
private UserMapper userMapper;
@Test
public void testInsert() {
User user = new User();
user.setName("测试用户");
// 自动填充:createUserId、createTime、updateUserId、updateTime
userMapper.insert(user);
}
@Test
public void testUpdate() {
User user = userMapper.selectById(1);
user.setName("修改后的名字");
// 自动填充:updateUserId、updateTime
userMapper.updateById(user);
}
}核心组件:@TableField(fill) 标记字段 + MetaObjectHandler 实现填充逻辑
通用规范:抽取 BaseEntity 基类,统一管理通用字段
填充规则:严格填充优先,有值不覆盖,null 不填充
业务优化:动态获取登录用户 ID,时间统一用 LocalDateTime
避坑关键:Spring 托管处理器、字段类型匹配、更新用对 API、参数名规范