TECH NOTES / Java 与 Spring

MyBatis-Plus 自动填充字段

原笔记 2021-10-09 · 整理于 2026-10-05

MyBatis-Plus 自动填充字段的配置与示例,记录创建和修改信息的统一处理。

示例说明:基类、请求上下文与当前用户的获取方式依赖业务项目;自动填充处理器需要按实际实体字段类型配置。

实体基类,每个实体都要有的属性

java
package com.leigq.www.mybatisplusstudy.domain.entity;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
import org.apache.ibatis.type.JdbcType;

import java.io.Serializable;
import java.time.LocalDateTime;

/**
 * 实体基类,每个实体都要有的属性
 *
 * @author leiguoqing
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
public class BaseEntity implements Serializable {

    /**
     * The constant serialVersionUID.
     */
    private static final long serialVersionUID = -6539444742613033263L;

    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Long id;

    /**
     * 创建人
     */
    @TableField(value = "created_by", fill = FieldFill.INSERT, jdbcType = JdbcType.BIGINT)
    private Long createdBy;

    /**
     * 创建时间
     */
    @TableField(value = "created_time", fill = FieldFill.INSERT, jdbcType = JdbcType.DATETIMEOFFSET)
    private LocalDateTime createdTime;

    /**
     * 修改人
     */
    @TableField(value = "updated_by", fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.BIGINT)
    private Long updatedBy;


    /**
     * 修改时间
     */
    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE, jdbcType = JdbcType.DATETIMEOFFSET)
    private LocalDateTime updatedTime;
}
java
package com.leigq.www.mybatisplusstudy.config;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Objects;


/**
 * MP自动填充参数
 *
 * @author leiguoqing
 * @date 2021 -10-9 9:03
 */
@Slf4j
@Component
public class MetaObjectHandlerConfig implements MetaObjectHandler {

    /**
     * 插入时填充
     *
     * @param metaObject the meta object
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        // 填充创建人id
        this.fillId(metaObject, IdType.CREATOR_ID);

        // 填充创建时间
        this.fillDate(metaObject, DateType.CREATE_TIME);

        // 填充修改人id
        this.fillId(metaObject, IdType.MODIFIER_ID);

        // 填充修改时间
        this.fillDate(metaObject, DateType.UPDATE_TIME);
    }


    /**
     * 更新时填充
     *
     * @param metaObject the meta object
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ....");
        // 填充修改人id
        this.fillId(metaObject, IdType.MODIFIER_ID);

        // 填充修改时间
        this.fillDate(metaObject, DateType.UPDATE_TIME);
    }


    /**
     * id类型
     */
    @Getter
    @AllArgsConstructor
    private enum IdType {
        /**
         * 创建人属性名称
         */
        CREATOR_ID("createdBy"),

        /**
         * 修改人属性名称
         */
        MODIFIER_ID("updatedBy"),
        ;

        /**
         * The Column name.
         */
        private final String columnName;
    }


    /**
     * 时间类型
     */
    @Getter
    @AllArgsConstructor
    private enum DateType {
        /**
         * 创建时间属性名称
         */
        CREATE_TIME("createdTime"),

        /**
         * 修改时间属性名称
         */
        UPDATE_TIME("updatedTime"),
        ;

        /**
         * The Column name.
         */
        private final String columnName;
    }


    /**
     * 填充员工id
     *
     * @param metaObject the meta object
     */
    private void fillId(MetaObject metaObject, IdType idType) {
        final boolean hasSetter = metaObject.hasSetter(idType.getColumnName());
        // 有 setter 方法才进行填充
        if (!hasSetter) {
            return;
        }

        final Object fieldVal = this.getFieldValByName(idType.getColumnName(), metaObject);
        // 属性为空才自动填充
        if (Objects.nonNull(fieldVal)) {
            return;
        }

        // 获取登录用户id, 0代表系统,有时数据是定时任务修改的,则为0
        final Long loginUserId = this.getLoginUserId();

        // 填充对应属性
        this.strictInsertFill(metaObject, idType.getColumnName(), Long.class, loginUserId);
    }


    /**
     * 填充时间
     *
     * @param metaObject the meta object
     */
    private void fillDate(MetaObject metaObject, DateType dateType) {
        final boolean hasSetter = metaObject.hasSetter(dateType.getColumnName());
        // 有 setter 方法才进行填充
        if (!hasSetter) {
            return;
        }

        final Object fieldVal = this.getFieldValByName(dateType.getColumnName(), metaObject);
        // 属性为空才自动填充
        if (Objects.nonNull(fieldVal)) {
            return;
        }

        // 填充对应属性
        this.strictInsertFill(metaObject, dateType.getColumnName(), LocalDateTime.class, LocalDateTime.now());
    }


    /**
     * 模拟获取登录用户id
     * <br/>
     * 默认为0,代表系统
     *
     * @return the login user id
     */
    private Long getLoginUserId() {
        // 模拟从请求头中获取jwt token
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        final String token = request.getHeader("token");

        if (StringUtils.isEmpty(token)) {
            return 0L;
        }
        // 正式环境应该从Redis缓存或者jwt中获取
        return 1L;
    }

}

文章配图