对比两个实体内部属性是否相同,不同时将差异结果记录下来

文章介绍了如何通过定义ObjectCompare注解和提供对比工具方法,简化在Java中对比对象属性的工作,减少大量if判断,提高代码效率。方法包括获取需要对比的字段、实体类字段描述、比较不同类型的字段以及动态给对象属性赋值。
摘要由CSDN通过智能技术生成

前言

对比两次提交记录,判断用户是否有修改信息,如有修改将修改前后结果保存下来。
由于字段太多,使用大量if判断,工作量太大。


1.定义注解,使用该注解的属性,会被对比

代码如下(示例):

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ObjectCompare {

    /**
     * 属性描述
     * @return
     */
    String value();

}

2.对比工具方法

代码如下(示例):

    /**
     * 对比两个相同类型实体属性
     *
     * @param obj1 对象1
     * @param obj2 对象2
     * @param clazz 类
     * @return List<ComparisonResult>
     */
    public static List<ComparisonResult> compareFields(Object obj1, Object obj2, Class clazz) throws Exception {
        try {
            List<String> ignoreList = getCompareFields(clazz);
            Map<String, String> descsMap = getFieldSwaggerValue(clazz);
            List<ComparisonResult> list = new ArrayList<>();

            // 两个对象是否同一类型
            if (obj1.getClass() == obj2.getClass()) {
                Class<?> claz = obj1.getClass();
                // 获取属性描述
                PropertyDescriptor[] pds = Introspector.getBeanInfo(claz, Object.class).getPropertyDescriptors();
                for (PropertyDescriptor pd : pds) {
                    String name = pd.getName().substring(0, 1).toLowerCase() + pd.getName().substring(1);
                    String label = descsMap.get(name);
                    if (!ignoreList.contains(name)) {
                        continue;
                    }
                    Method readMethod = pd.getReadMethod();
                    Object o1 = readMethod.invoke(obj1);
                    Object o2 = readMethod.invoke(obj2);
                    String r1 = null, r2 = null;
                    if (Objects.isNull(o1) && Objects.isNull(o2)) {
                        continue;
                    }
                    if (null == o1 || null == o2) {
                        setResult(o1, o2, name, label, list);
                        continue;
                    }
                    if (compareField(o1, o2)) {
                        setResult(o1, o2, name, label, list);
                    }
                }
            } else {
                throw new Exception("比较的对象类型不一致");
            }
            return list;
        } catch (Exception e) {
            throw new Exception("对象比较失败", e);
        }
    }
    /**
     * 获取需要对比的字段
     *
     * @param objectClass
     * @return
     */
    private static List<String> getCompareFields(Class objectClass) {
        Field[] fields = objectClass.getDeclaredFields();
        List<String> map = new ArrayList<>();
        for (Field f : fields) {
            boolean annotationPresent2 = f.isAnnotationPresent(ObjectCompare.class);
            if (annotationPresent2) {
                map.add(f.getName());
            }
        }
        return map;
    }
    /**
     * 获取实体类字段的description
     *
     * @param clazz
     * @return
     */
    private static Map<String, String> getFieldSwaggerValue(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        Map<String, String> map = new HashMap<>();
        for (Field f : fields) {
            boolean annotationPresent2 = f.isAnnotationPresent(ObjectCompare.class);
            if (annotationPresent2) {
                ObjectCompare name = f.getAnnotation(ObjectCompare.class);
                String nameStr = name.value();
                map.put(f.getName(), nameStr);
            }
        }
        return map;
    }
    /**
     * 比较字段
     *
     * @param o1 对象1
     * @param o2 对象2
     * @return boolean
     **/
    private static boolean compareField(Object o1, Object o2) {
        boolean sign = false;
        Object ot = null;
        if (!Objects.isNull(o1)) {
            ot = o1;
        } else if (!Objects.isNull(o2)) {
            ot = o2;
        }
        if (ot instanceof String) {
            sign = !o1.equals(o2);
        } else if (ot instanceof BigDecimal) {
            sign = ((BigDecimal) o1).compareTo((BigDecimal) o2) != 0;
        } else if (ot instanceof Integer) {
            sign = ((Integer) o1).compareTo((Integer) o2) != 0;
        } else if (ot instanceof Boolean) {
            sign = ((Boolean) o1).compareTo((Boolean) o2) != 0;
        } else if (ot instanceof Long) {
            sign = ((Long) o1).compareTo((Long) o2) != 0;
        } else if (ot instanceof LocalDateTime) {
            sign = !((LocalDateTime) o1).isEqual((LocalDateTime) o2);
        } else if (ot instanceof Date) {
            sign = ((Date) o1).compareTo((Date) o2) != 0;
        }
        return sign;
    }
    /**
     * 设置结果
     *
     * @param o1    对象1
     * @param o2    对象2
     * @param name  描述
     * @param label 标签
     * @param list  列表
     **/
    private static void setResult(Object o1, Object o2, String name, String label, List<ComparisonResult> list) {
        ComparisonResult result = new ComparisonResult();
        result.setKey(name);
        result.setPrevious(o1);
        result.setLater(o2);
        result.setLabel(label);
        list.add(result);
    }

3.对比工具方法

代码如下(示例):

    /**
     * 动态给Java对象指定的属性赋值
     *
     * @param obj       要设置值的对象
     * @param fieldName 要设置值的属性名称
     * @param value     要设置的值
     */
    public static void setFieldValueByName(Object obj, String fieldName, Object value) {
        try {
            // 获取obj类的字节文件对象
            Class<? extends Object> c = obj.getClass();
            // 获取该类的成员变量
            Field field = c.getDeclaredField(fieldName);
            // 取消语言访问检查
            field.setAccessible(true);
            // 给变量赋值
            field.set(obj, value);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值