MP字段自动填充策略

265 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第25天,点击查看活动详情

一、作用

有些表中会有更新时间、创建时间、更新人或者创建人这些字段。每次对数据进行新增、删除、修改时都需要对这些字段进行设置。传统的做法是在进行这些操作前,对Entity的字段进行set设置,然后再进行操作。这种做法不仅容易忘记导致出错、而且代码会显得特别冗余。所以MP就提供自动填充的功能,帮助自定设置这些字段的值,提升开发效率,代码也会显得特别优雅。

二、实现,实体类需要自动填充字段添加@TableField注解

在实体类中添加@TableField注解,选择合适的填充策略

@TableField注解直接枚举类型FieldFill

@TableField(fill=FieldFill.INSERT或者@TableField(fill = FieldFill.INSERT_UPDATE)

/**
 * 创建时间
 */
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;

/**
 * 更新时间
 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;

/**
 * 创建人
 */
@TableField(fill = FieldFill.INSERT)
private Long createUser;

/**
 * 修改人
 */
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updateUser;

三、 自定义数据对象处理器实现MetaObjectHandler接口,并重写内部两个方法。

updateFill(MetaObject metaObject)
insertFill(MetaObject metaObject)
/**
 * 自定义元数据对象处理器
 */
@Component
@Slf4j
public class MyMetaObjecthandler implements MetaObjectHandler {
    /**
     * 插入操作,自动填充
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("公共字段自动填充[insert]...");
        log.info(metaObject.toString());
        metaObject.setValue("createTime", LocalDateTime.now());
        metaObject.setValue("updateTime",LocalDateTime.now());
        metaObject.setValue("createUser", BaseContext.getCurrentId());
        metaObject.setValue("updateUser",BaseContext.getCurrentId());
    }

    /**
     * 更新操作,自动填充
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("公共字段自动填充[update]...");
        log.info(metaObject.toString());

        long id = Thread.currentThread().getId();
        log.info("线程id为:{}",id);

        metaObject.setValue("updateTime",LocalDateTime.now());
        metaObject.setValue("updateUser",BaseContext.getCurrentId());
    }
}

方法内部主要是填写字段要填充内容的逻辑。其中metaObject参数可以获取请求参数,而我们要做的是通过metaObject调用setValue(String name,Object value)来填充公共字段的值;MetaObjectHandler提供的默认方法的策略均为:如果属性有值则不覆盖,如果填充值为null则不填充

注意:这里一定要给实现类加上注解 @Component,让容器管理这个Bean

四、原理

上述代码可以看出输入参数只有metaObject,并没有请求参数,那么如何获取会话中的内容那?

首先客户端向服务端发送http请求时,服务端会创建一个新的线程来处理请求。那个共用一个线程的操作可以通过TreadLocal共享变量,故可以创建一个工具类,在我们要填充公共字段之前的操作(含有请求参数HttpServletRequest)中,事先将Session中的变量放进去,最后在MetaObjectHandler接口实现类中获取这个变量。