携手创作,共同成长!这是我参与「掘金日新计划 · 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接口实现类中获取这个变量。