插入或更新的时候为指定字段赋予指定的值,可以减少重复代码。
实现
- 在实体类的属性上加入@TableField注解,指定自动填充的策略
@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接口
-
/** * 自定义元数据对象处理器 */ @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", new Long(1)); metaObject.setValue("updateUser", new Long(1)); } /** * 更新操作,自动填充 * @param metaObject */ @Override public void updateFill(MetaObject metaObject) { log.info("公共字段自动填充[update]..."); log.info(metaObject.toString()); metaObject.setValue("updateTime", LocalDateTime.now()); metaObject.setValue("updateUser", new Long(1)); } }
动态地获取id的值——ThreadLocal:
ThreadLocal是线程Thread的局部变量,当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,与其它线程互不影响。这是因为ThreadLocal为每个线程提供单独一份存储空间,具有线程隔离的效果,只有线程内才能获取到对应的值,线程外不能访问。
ThreadLocal常用方法:
- public void set(T value) 设置当前线程的线程局部变量的值
- public T get() 返回当前线程所对应的线程局部变量的值
由于LoginCheckFilter和MyMetaObjectHandler处于同一线程,因此依据以上ThreadLocal的性质,可以在LoginCheckFilter的doFilter方法中获取当前登录用户id,因为doFilter里可以获取session(session里存有用户id),并调用ThreadLocal的set方法来设置当前线程的线程局部变量的值(用户id),然后在MyMetaObjectHandler的updateFill方法中调用ThreadLocal的get方法来获得当前线程局部变量的值(用户id)。
具体编码步骤如下:
- 编写BaseContext工具类,基于ThreadLocal封装的工具类
/**
* 基于ThreadLocal封装工具类,用户保存和获取当前用户id
*/
public class BaseContext {
public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
/**
* 设置值
* @param id
*/
public static void setCurrentId(Long id){
threadLocal.set(id);
}
/**
* 获取值
* @return
*/
public static Long getCurrentId(){
return threadLocal.get();
}
}
2.在LoginCheckFilter.java里设置empId,使用1中的BaseContext的set方法存储该用户Id
//设置empId
Long empId = (Long) request.getSession().getAttribute("employee");
BaseContext.setCurrentId(empId);
3.在MyMetaObjectHandler.java中,通过BaseContext的get方法获取用户id
metaObject.setValue("createTime", LocalDateTime.now());
metaObject.setValue("updateTime", LocalDateTime.now());
metaObject.setValue("createUser", BaseContext.getCurrentId());
metaObject.setValue("updateUser", BaseContext.getCurrentId());