前言:在mybatis-plus的公共字段自动填充功能中有多种填充方式,以下将通过源码对各种填充方法进行剖析
相信了解mybatis-plus公共字段自动填充功能的同学对MetaObjectHandler
接口并不陌生,我们把MetaObjectHandler
接口整理一下,只关注他的注入字段部分(结论在下面)
public interface MetaObjectHandler {default MetaObjectHandler setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject) {if (Objects.nonNull(fieldVal) && metaObject.hasSetter(fieldName)) {metaObject.setValue(fieldName, fieldVal);}return this;}default MetaObjectHandler strictInsertFill(TableInfo tableInfo, MetaObject metaObject, List<StrictFill<?, ?>> strictFills) {return strictFill(true, tableInfo, metaObject, strictFills);}default MetaObjectHandler strictUpdateFill(TableInfo tableInfo, MetaObject metaObject, List<StrictFill<?, ?>> strictFills) {return strictFill(false, tableInfo, metaObject, strictFills);}default MetaObjectHandler strictFill(boolean insertFill, TableInfo tableInfo, MetaObject metaObject, List<StrictFill<?, ?>> strictFills) {if ((insertFill && tableInfo.isWithInsertFill()) || (!insertFill && tableInfo.isWithUpdateFill())) {strictFills.forEach(i -> {final String fieldName = i.getFieldName();final Class<?> fieldType = i.getFieldType();tableInfo.getFieldList().stream().filter(j -> j.getProperty().equals(fieldName) && fieldType.equals(j.getPropertyType()) &&((insertFill && j.isWithInsertFill()) || (!insertFill && j.isWithUpdateFill()))).findFirst().ifPresent(j -> strictFillStrategy(metaObject, fieldName, i.getFieldVal()));});}return this;}default MetaObjectHandler fillStrategy(MetaObject metaObject, String fieldName, Object fieldVal) {if (getFieldValByName(fieldName, metaObject) == null) {setFieldValByName(fieldName, fieldVal, metaObject);}return this;}default MetaObjectHandler strictFillStrategy(MetaObject metaObject, String fieldName, Supplier<?> fieldVal) {if (metaObject.getValue(fieldName) == null) {Object obj = fieldVal.get();if (Objects.nonNull(obj)) {metaObject.setValue(fieldName, obj);}}return this;}
}
此时有6个方法可以进行字段填充
setFieldValByName()
strictInsertFill()
strictUpdateFill()
strictFill()
fillStrategy()
strictFillStrategy()
我们逐个进行分析
setFieldValByName()
当要注入的值fieldVal
不为空,则注入,被fillStrategy()
方法代替strictInsertFill()
strictUpdateFill()
以上两个方法都是直接封装后调用strictFille()
,可以忽略strictFill()
校验实体表里的字段与要注入的公共字段的数据的名称和类型是否一致、实体类上是否有@TableField(fill = FieldFill.xxx)
注解,再调用strictFillStrategy()
方法进行填充fillStrategy()
在直接调用setFieldValByName()
的基础上,做了一层安全校验
若元数据的该字段为null,且fieldVal
不为空才注入strictFillStrategy()
若元数据的该字段为null,且fieldVal
不为空才注入,被strictFill()
方法代替
由于fillStrategy()
和strictFillStrategy()
比较相似,可以一下比较这两个方法
default MetaObjectHandler fillStrategy(MetaObject metaObject, String fieldName, Object fieldVal) {//把getFieldValByName()和setFieldValByName()方法体内的代码进行替换并简化if (metaObject.getValue(fieldName) == null) {if (Objects.nonNull(fieldVal)) {metaObject.setValue(fieldName, fieldVal);}}return this;
}default MetaObjectHandler strictFillStrategy(MetaObject metaObject, String fieldName, Supplier<?> fieldVal) {if (metaObject.getValue(fieldName) == null) {Object obj = fieldVal.get();//不同点if (Objects.nonNull(obj)) {metaObject.setValue(fieldName, obj);}}return this;
}
可以看出两个方法只在参数fieldVal
上有区别
相比之下strictFillStrategy()
在fieldVal
的校验上更加严格
此时可用的方法只剩strictFill()
和fillStrategy()
,两个方法的不同点在于:
strictFill()
的安全校验包含了fillStrategy()
的安全校验,同时也判断了数据库中是否有这个字段、实体类上是否有@TableField(fill = FieldFill.xxx)
注解