Mybatis Plus实现公共字段的自动填充

251 阅读2分钟

问题背景

在Insert和Update中,存在一些用同样方法处理的字段(公共字段),而每次对公共字段进行相同的处理方式会显得代码臃肿。

image.png

employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
employee.setCreateUser((Long) httpSession.getAttribute("employee"));
employee.setUpdateUser((Long) httpSession.getAttribute("employee"));

mybatis plus正好能解决对公共字段的自动填充

实现方法

1:在要进行自动填充的属性上加入@TableField注解

@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = "yyyy-mm-dd HH:mm:ss")
@
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;

其中fill属性表示在哪个方法下进行自动填充,FieldFill.INSERT为插入语句,UPDATE为更新语句,INSERT_UPDATE为插入和更新语句。

区分一下@JsonFormat和@DateTimeFormat

@JsonFormat: pattern:与前端交换数据时,将数据在Json(前端)和Date(后端)类型中以约束的格式进行转换

timezone:设置时区,将自动把系统时间增减时区

@DateTimeFormat:将前端传入的String转换为Date时以约束的格式进行转换,但后端的数据为不会被该格式约束。若前端传回来的为Json格式,则需要用@RequestBody将Json转换为Date类型,此时需要Json的时间格式和DateTimeFormat所约束的格式相同

2:实现MetaObjectHandler

@Component
public class MetaObjectHandlerImpl implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        metaObject.setValue("createTime", LocalDateTime.now());
        metaObject.setValue("updateTime", LocalDateTime.now());
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        metaObject.setValue("updateTime", LocalDateTime.now());
    }
}

由于无法获得session,因此通过ThreadLocal对id进行临时的存储

3:ThreadLocal存储数据

使用条件

Threadlocal只能用在同一线程内。每一个请求为同一个线程,因此可以将用户id在过滤器中存储,并在MetaObjetHandlerImol中取出。

Threadlocal是以对象为key值,因此一次只能存储一个数据,使用时必须保障为同一个Threadlocal对象。

public class ThreadLocalId {
    private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();

    public static void setId(Long id) {
        threadLocal.set(id);
    }
    public static Long getId(){
        return threadLocal.get();
    }
}

使用static修饰能保证为同一个Threadlocal对象

Long employeeId = (Long) httpServletRequest.getSession().getAttribute("employee");
if (employeeId != null) {
    ThreadLocalId.setId(employeeId);
    filterChain.doFilter(servletRequest,servletResponse);
    return;
}

并在过滤器中将id存入Threadlocal

@Component
public class MetaObjectHandlerImpl implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
        metaObject.setValue("createTime", LocalDateTime.now());
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("createUser", ThreadLocalId.getId());
        metaObject.setValue("updateUser", ThreadLocalId.getId());
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        metaObject.setValue("updateTime", LocalDateTime.now());
        metaObject.setValue("updateUser", ThreadLocalId.getId());
    }
}

4:总结

1: @TableField标记需要自动填充的属性

2:实现MetaObjectHandler并实现insertFill和updateFill

3:可以通过Threadlocal在同一线程中存取数据