项目中使用到了Mybatis-plus的自动填充功能。看了下自动填充的大致使用。
1.实现MetaObjectHandler
重写insertFill()
以及updateFill()
。
public class MetaHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
LocalDateTime now = LocalDateTime.now();
// Date now = new Date();
if (this.getFieldValByName("createTime", metaObject) == null) {
strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
}
if (this.getFieldValByName("updateTime", metaObject) == null) {
this.setFieldValByName("updateTime", now, metaObject);
}
if (this.getFieldValByName("status", metaObject) == null) {
this.setFieldValByName("status", 1, metaObject);
}
}
@Override
public void updateFill(MetaObject metaObject) {
if (this.getFieldValByName("updateTime", metaObject) == null) {
this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
}
}
}
2.注入容器
3.编写配置类
@Bean
public GlobalConfig globalConfig() {
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setMetaObjectHandler(new MetaHandler());
return globalConfig;
}
4.entity增加注解
@TableField(fill = FieldFill.INSERT)
@JsonFormat(pattern = DateUtil.FORMAT_2)
protected LocalDateTime createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
@JsonFormat(pattern = DateUtil.FORMAT_2)
protected LocalDateTime updateTime;
一切都很正常,实际使用中缺失效了。查看问题原因发现:
因为项目中公用字段写到了BaseDO,所以有些entity没有继承BaseDO或者即使继承了但重载了createTime
updateTime
并且没有增加注解。
针对这种重载情况,mybatis-plus只会扫描子类的。
List<Field> list = getAllFields(clazz);
public static List<Field> getAllFields(Class<?> clazz) {
List<Field> fieldList = ReflectionKit.getFieldList(ClassUtils.getUserClass(clazz));
return fieldList.stream()
.filter(field -> {
/* 过滤注解非表字段属性 */
TableField tableField = field.getAnnotation(TableField.class);
return (tableField == null || tableField.exist());
}).collect(toList());
}
public static List<Field> getFieldList(Class<?> clazz) {
if (Objects.isNull(clazz)) {
return Collections.emptyList();
}
return CollectionUtils.computeIfAbsent(CLASS_FIELD_CACHE, clazz, k -> {
Field[] fields = k.getDeclaredFields();
List<Field> superFields = new ArrayList<>();
Class<?> currentClass = k.getSuperclass();
while (currentClass != null) {
Field[] declaredFields = currentClass.getDeclaredFields();
Collections.addAll(superFields, declaredFields);
currentClass = currentClass.getSuperclass();
}
/* 排除重载属性 */
Map<String, Field> fieldMap = excludeOverrideSuperField(fields, superFields);
/*
* 重写父类属性过滤后处理忽略部分,支持过滤父类属性功能
* 场景:中间表不需要记录创建时间,忽略父类 createTime 公共属性
* 中间表实体重写父类属性 ` private transient Date createTime; `
*/
return fieldMap.values().stream()
/* 过滤静态属性 */
.filter(f -> !Modifier.isStatic(f.getModifiers()))
/* 过滤 transient关键字修饰的属性 */
.filter(f -> !Modifier.isTransient(f.getModifiers()))
.collect(Collectors.toList());
});
}
public static Map<String, Field> excludeOverrideSuperField(Field[] fields, List<Field> superFieldList) {
// 子类属性
Map<String, Field> fieldMap = Stream.of(fields).collect(toMap(Field::getName, identity(),
(u, v) -> {
throw new IllegalStateException(String.format("Duplicate key %s", u));
},
LinkedHashMap::new));
superFieldList.stream().filter(field -> !fieldMap.containsKey(field.getName()))
.forEach(f -> fieldMap.put(f.getName(), f));
return fieldMap;
}
上面的代码测试 有值也会覆盖填充。