美文网首页
JAVA 通用寻找对象间差异的所有字段

JAVA 通用寻找对象间差异的所有字段

作者: 爱余星痕 | 来源:发表于2020-03-30 15:24 被阅读0次

最近在做某个项目中,需要查找多个属性间不同的字段,但这些属性很多,一个一个的字段比较,很折腾,所以就自己写了一个快速的框架.
1.定义需要对比的结果,有新增,变更,删除,无变化四种结果

   public enum  CompareStatus {
    /**
     * 标记新数据
     */
    NEW,
    /**
     * 标记变更数据
     */
    CHANGE,
    /**
     * 标记删除数据
     */
    DELETE,
    /**
     * 标记没有变更
     */
    NO_CHANGE;

}
  1. 定义对比的结果类
    @AllArgsConstructor
@NoArgsConstructor
@Data
public class CompareResult {

    /**
     * 差异的结果属性
     */
    private String propertyName;
    /**
     * 原来的属性
     */
    private Object originalValue;


    /**
     *  当前的属性
     */
    private Object currentValue;
}
  1. 具体对比的结果方法及实现
@Data
@Slf4j
public class CompareObject<T> {


    private CompareStatus status;
    /**
     * 之前原始的值
     */
    private T original;
    /**
     * 当前的值
     */
    private T current;

    /**
     * 需要对比的属性
     */
    private List<String> includePropertys = new ArrayList<>();

    /**
     * 需要排除的属性
     */
    private List<String> excludePropertys = new ArrayList<>();

    /**
     * 不相等的比较结果
     */
    private List<CompareResult> noEqualCompareResults = new ArrayList<>();


    /**
     * 值相同比较结果
     */
    private List<CompareResult> equalCompareResults = new ArrayList<>();

    /**
     * 计算比较结果
     * @param cls 比较的类
     */
    public void compareDiff(Class<T> cls) {

        Assert.notNull(this.current, "不允许当前比较对象为空");
        boolean isEqual = true;
        //clazz.getDeclaredFields()不能获取父的属性
        Field[] fields = this.getAllFields(cls);
        for(Field field : fields) {
            try {
                //判断属性是否在包含的属性里面
                if (CollectionUtils.isNotEmpty(this.includePropertys) && !this.includePropertys
                        .contains(field.getName())) {
                    continue;
                }
                //判断属性是否在排除的包含属性里面
                if (CollectionUtils.isNotEmpty(this.excludePropertys) && this.excludePropertys
                        .contains(field.getName())) {
                    continue;
                }
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), cls);
                Method getMethod = pd.getReadMethod();
                Object o1 = this.original == null ? null : getMethod.invoke(this.original);
                Object o2 = this.current == null ? null : getMethod.invoke(this.current);
                CompareResult compareResult = new CompareResult(field.getName(), o1, o2);
                //判断是否有自定义注解
                if (field.getDeclaredAnnotation(CompareSpi.class) != null) {
                    CompareSpi compareSpi = field.getDeclaredAnnotation(CompareSpi.class);
                    //自定义比较内容
                    CompareSpiService compareSpiService = (CompareSpiService) compareSpi.compareClass().newInstance();
                    if (compareSpiService.compareObject(o1, o2)) {
                        this.equalCompareResults.add(compareResult);
                    } else {
                        isEqual = false;
                        this.noEqualCompareResults.add(compareResult);
                    }
                } else {
                    if (Objects.equals(o2, o1)) {
                        this.equalCompareResults.add(compareResult);
                    } else {
                        isEqual = false;
                        this.noEqualCompareResults.add(compareResult);
                    }
                }
            } catch (Exception e) {
             log.debug(e.getMessage());
            }
        }
        if (this.original == null) {
            this.status = CompareStatus.NEW;
        } else if (isEqual) {
            this.status = CompareStatus.NO_CHANGE;
        } else {
            this.status = CompareStatus.CHANGE;
        }

    }

    private Field[] getAllFields(Class clazz) {
        List<Field> fieldList = new ArrayList<>();
        while (clazz != null) {
            fieldList.addAll(new ArrayList<>(Arrays.asList(clazz.getDeclaredFields())));
            clazz = clazz.getSuperclass();
        }
        Field[] fields = new Field[fieldList.size()];
        fieldList.toArray(fields);
        return fields;
    }


 
}
  1. 测试具体调用的方法
        BaseModel orgDepartmentDto = new BaseModel();
        orgDepartmentDto.setCreateUserCode("1111");
        BaseModel orgDepartmentDto2 = new BaseModel();
        orgDepartmentDto2.setCreateUserCode("122211");
        CompareObject<BaseModel> compareObject = new CompareObject<>();
        compareObject.setCurrent(orgDepartmentDto);
        compareObject.setOriginal(orgDepartmentDto2);
        compareObject.compareDiff(BaseModel.class);
        log.info(compareObject.getStatus().name());
        log.info(compareObject.getEqualCompareResults().toString());
        log.info(compareObject.getNoEqualCompareResults().toString());

自此,就能快速的获取两个对象的差异,而不需要一个一个属性的比较

相关文章

  • JAVA 通用寻找对象间差异的所有字段

    最近在做某个项目中,需要查找多个属性间不同的字段,但这些属性很多,一个一个的字段比较,很折腾,所以就自己写了一个快...

  • 获取Java对象的所有字段值

    问题 在对接第三方的请求接口时,POST传参要求的格式类似GET的params;请求内容类型,这里为 applic...

  • JAVA与C++的差异(2)

    JAVA与C++的差异(2)
    JAVA的面向对象 类的所有方法,均为虚方法(虚函...

  • java反射

    一切皆对象 java中所有的东西都有对应的对象,包括包,类,方法,字段,注解,一切皆对象。包package对应的类...

  • java反射机制

    一切皆对象 java中所有的东西都有对应的对象,包括包,类,方法,字段,注解,一切皆对象。包package对应的类...

  • java反射

    一切皆对象 java中所有的东西都有对应的对象,包括包,类,方法,字段,注解,一切皆对象。包package对应的类...

  • Android的面试知识点

    JAVA方面 1、权限的关键字段 public, private, protected 2、java面向对象特点 ...

  • 数据表设计 - 特殊字段说明

    1.系统通用的隐藏字段 所有数据表都有的系统通用隐藏字段,并且这些字段一般情况下客户不需要看到 mis_versi...

  • Effective Java——对于所有对象都通用的方法

    本系列文章是总结Effective Java文章中我认为最重点的内容,给很多没时间看书的朋友以最短的时间看到这本书...

  • Effective Java:对于所有对象都通用的方法

    第8条:覆盖equals时请遵守通用约定 (Item 8: Obey the general contract w...

网友评论

      本文标题:JAVA 通用寻找对象间差异的所有字段

      本文链接:https://www.haomeiwen.com/subject/gajvuhtx.html