mybatis-plus自动填充字段 MetaObjectHandler

给实体类需要自动填充的字段添加注解

注解中的fill属性表示字段填充标记,配合自动填充使用。
fill对应的值:
DEFAULT : 默认不处理
INSERT :插入操作时进行填充字段
UPDATE :更新操作时填充字段
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接口

当需要执行新增或者修改操作的时候,业务层对实体类属性赋值,但是,createTime、updateTime、createUser、updateUser这四个属性除外,因为它们统一由当前类的metaObject对象进行赋值,值的来源根据实际情况而定,比如createTime和updateTime获取的当前系统时间,creatUser和updateUser为修改人,可以通过ThreadLocal获取,也可以从通过springboot自动注入的方式把Requset注入过来,从前端请求给的JWT中拿ID。

@Component //需要将当前类交给spring容器保管
public class MyMetaObjecthandler implements MetaObjectHandler {
    /**
     * 插入操作,自动填充。所有执行insert语句的时候执行该方法
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        System.out.println("metaObject-insert = " + metaObject);
        metaObject.setValue("createTime", LocalDateTime.now());  // 添加用户时间
        metaObject.setValue("updateTime", LocalDateTime.now());  // 修改用户时间
        metaObject.setValue("createUser", BaseContext.getCurrentId());    // 添加人的id
        metaObject.setValue("updateUser", BaseContext.getCurrentId());    // 更新人的id
    }
    /**
     * 更新操作,自动填充。所有执行update语句的时候执行该方法
     * @param metaObject
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        System.out.println("metaObject-update = " + metaObject);

        long id = Thread.currentThread().getId();
        log.info("线程id = " + id);

        metaObject.setValue("updateTime", LocalDateTime.now());  // 修改用户时间
        metaObject.setValue("updateUser", BaseContext.getCurrentId());    // 更新人的id
    }

这里补充一下ThreadLocal的介绍

ThreadLocal叫做线程变量,意思是ThreadLocal中填充的变量属于当前线程,该变量对其他线程而言是隔离的,也就是说该变量是当前线程独有的变量。ThreadLocal为变量在每个线程中都创建了一个副本,那么每个线程可以访问自己内部的副本变量。
ThreadLoal 变量,线程局部变量,同一个 ThreadLocal 所包含的对象,在不同的 Thread 中有不同的副本。这里有几点需要注意:
因为每个 Thread 内有自己的实例副本,且该副本只能由当前 Thread 使用。这是也是 ThreadLocal 命名的由来。
既然每个 Thread 有自己的实例副本,且其它 Thread 不可访问,那就不存在多线程间共享的问题。
总结两个作用

  1. 保证线程安全
  2. 在线程级别传递变量

使用方法 这里可以理解是set复制 get获取值,特定情景进行变量储存

/**
 * 基于ThreadLocal封装工具类,用户保存和获取当前登录用户id
 */
public class BaseContext {
    private static ThreadLocal<Long> threadLocal = new ThreadLocal<Long>();
    /**
     *  添加Id值
     * @param id
     */
    public static void setCurrentId(Long id) {
        threadLocal.set(id);
    }

    /**
     *   获取Id值
     * @return
     */
    public static Long getCurrentId() {
        return threadLocal.get();
    }
}
posted @ 2022-08-07 19:44  小源博客  阅读(559)  评论(0)    收藏  举报