Mybatis Plus公共字段自动填充,也就是在插入或者更新的时候如果发现某些字段为空,则为其赋予指定的默认值。
【1】几个概念
① FieldFill枚举类
public enum FieldFill { DEFAULT(0, "默认不处理"), INSERT(1, "插入填充字段"), UPDATE(2, "更新填充字段"), INSERT_UPDATE(3, "插入和更新填充字段"); /** * 主键 */ private final int key; /** * 描述 */ private final String desc; //... }
② MetaObjectHandler元数据处理器接口
MetaObjectHandler是一个抽象类,元对象字段填充控制器抽象类,实现公共字段自动写入。其提供了两个抽象方法供开发者实现(插入元对象字段填充和更新元对象字段填充(用于更新时对公共字段的填充)):
/** * <p> * 插入元对象字段填充 * </p> * * @param metaObject 元对象 */ public abstract void insertFill(MetaObject metaObject); /** * 更新元对象字段填充(用于更新时对公共字段的填充) * Created with IntelliJ IDEA. * Author: Wu Yujie * Email: coffee377@dingtalk.com * Time: 2017/04/16 15:03 * * @param metaObject 元对象 */ public abstract void updateFill(MetaObject metaObject);
③ 什么是metaobject元对象?
metaobject,元对象 , 是 Mybatis提供的一个用于更加方便,更加优雅的访问对象的属性 ,给对象的属性 设置值 的一个对象。还会用于包装对象 . 支持对 Object 、 Map、Collection等对象进行包装。
本质上 metaObject获取对象的属性值或者是给对象的属性设置值,最终是要通过Reflector 获取到属性的对应方法的 Invoker, 最终 invoke实现。
【2】开发步骤
① 注解填充字段
@TableField(fill=FieldFill.INSERT_UPDATE)
注解标注在需要填充属性值的字段上,当然这里fill=FieldFill.INSERT_UPDATE
(插入或更新)你可以选择其他。实例如下:
public class User extends Parent { private Integer id ; @TableField(fill=FieldFill.INSERT_UPDATE) private String name ; //... }
② 自定义公共字段填充处理器
实例如下:
/** * 自定义公共字段填充处理器 */ public class MyMetaObjectHandler extends MetaObjectHandler { /** * 插入操作 自动填充 */ @Override public void insertFill(MetaObject metaObject) { //获取到需要被填充的字段的值 Object fieldValue = getFieldValByName("name", metaObject); if(fieldValue == null) { setFieldValByName("name", "jane", metaObject); } } /** * 修改操作 自动填充 */ @Override public void updateFill(MetaObject metaObject) { Object fieldValue = getFieldValByName("name", metaObject); if(fieldValue == null) { setFieldValByName("name", "janus", metaObject); } } }
③ MP全局注入自定义公共字段填充处理器
其实就是添加到Configuration中,实例如下:
<!-- 定义MybatisPlus的全局策略配置--> <bean id ="globalConfiguration" class="com.baomidou.mybatisplus.entity.GlobalConfiguration"> <!-- 在2.3版本以后,dbColumnUnderline 默认值就是true --> <property name="dbColumnUnderline" value="true"></property> <!-- Mysql 全局的主键策略 --> <!-- <property name="idType" value="0"></property> --> <!-- Oracle全局主键策略 --> <property name="idType" value="1"></property> <!-- 全局的表前缀策略配置 --> <property name="tablePrefix" value="tbl_"></property> <!-- 注入公共字段填充处理器 --> <property name="metaObjectHandler" ref="myMetaObjectHandler"></property> </bean> <!-- 公共字段填充 处理器 --> <bean id="myMetaObjectHandler" class="com.jane.mp.metaObjectHandler.MyMetaObjectHandler"> </bean>
测试结果如下图(update时会默认为name赋值):
【4】SpringBoot下使用MyMetaObjectHandler
① MyMetaObjectHandler配置类
这里我们实现createTime和updateTime的自动填充。
@Configuration public class MyMetaObjectHandler implements MetaObjectHandler { // 自动插入公公字段 @Override public void insertFill(MetaObject metaObject) { if (metaObject.hasSetter("createTime")&&getFieldValByName("createTime",metaObject)==null) { setInsertFieldValByName("createTime", new Date(), metaObject); //setInsertFieldValByName("updateTime", LocalDateTime.now(), metaObject); } } // 自动更新公共字段 @Override public void updateFill(MetaObject metaObject) { if (metaObject.hasSetter("updateTime")&&getFieldValByName("updateTime",metaObject)==null) { setUpdateFieldValByName("updateTime", new Date(), metaObject); } } }
② 实体类属性需要添加注解
@TableField(value = "create_time",fill = FieldFill.INSERT) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date createTime; @TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private Date updateTime;
【5】实现原理
如下图所示,如果熟悉mybatis执行流程的同学应该很熟悉。
在整个语句执行流程中,我们会在BaseStatementHandler的构造函数中看到parameterHandler的实例化。
.
继续追踪其实例化的过程中,我们可以看到参数的预处理:
在processParameter中就会尝试找到一个metaObjectHandler进行insert或者update的处理。