专栏首页JAVA后端开发JAVA 通用寻找对象间差异的所有字段

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

最近在做某个项目中,需要查找多个属性间不同的字段,但这些属性很多,一个一个的字段比较,很折腾,所以就自己写了一个快速的框架. 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());

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • activiti explorer跨模板复制流程节点

    最近的项目是用activiti explorer做流程前端。 功能做出来后,经常被用户反馈 ,说流程页面不好用。 画一个流程图后,再画一个,都要重头开始,如...

    星痕
  • 解决el-dialog使用时无法正常弹出的问题

    在使用el-dialog,发现无论怎么做,该对话框也无法显示,前端也没有报错. 点击按钮时,发现遮罩层已经出来了,但对话框没有显示. 经查,缺少属性appe...

    星痕
  • swagger设置全局token,解决接口需要token验证的问题

    swagger是一个很牛B的东东,但正常使用时,我们的接口需要登陆才能访问的。即登陆时,要传一个登陆后的token才能访问的。 那这个怎么设置,才可以让所有接...

    星痕
  • 聊聊rocketmq的getOrCreateMQClientInstance

    本文主要研究一下rocketmq的getOrCreateMQClientInstance

    codecraft
  • 聊聊rocketmq的getOrCreateMQClientInstance

    本文主要研究一下rocketmq的getOrCreateMQClientInstance

    codecraft
  • Hadoop数据分析平台实战——250JSSDK数据收集引擎编写离线数据分析平台实战——250JSSDK数据收集引擎编写

    离线数据分析平台实战——250JSSDK数据收集引擎编写 JsSDK设计规则 在js sdk中我们需要收集launch、pageview、chargeReque...

    Albert陈凯
  • 突然顿悟的Javascript中的this

      一直对Javascript中的this都有一种似是而非的感觉,今天突然感觉豁然开朗,特此记录一下。 咱们先看个栗子: <!DOCTYPE html> <ht...

    hbbliyong
  • 归纳总结this的指向问题

    7.函数调用时如果绑定了bind,那么函数中的this指向了bind中绑定的元素

    FinGet

扫码关注云+社区

领取腾讯云代金券