MybatisPlus自动填充失效

ima
ima
2021-08-12 / 0 评论 / 54 阅读
温馨提示:
本文最后更新于2021-08-12,若内容或图片失效,请留言反馈。

项目中使用到了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;
    }

上面的代码测试 有值也会覆盖填充。