Java 反射实现修改操作比较两个对象不同之处

220 阅读1分钟

背景:需要记录操作的变更记录,修改后的对象与原对象进行比较会存在大量if的判断。 措施:使用Java反射比较两个对象的不同属性值,实现数据库修改操作的日志记录。

1、自定义注解,标识对象需要比较的字段

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CompareField {
    String value();
}

2、在实体的指定字段上使用注解

@ApiModel(value="BcBuildingPark对象", description="园区表")
@Data
@TableName("building_park")
public class BuildingPark implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "园区id")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @CompareField(value = "园区名称")
    @ApiModelProperty(value = "园区名称")
    private String name;

    @ApiModelProperty(value = "园区所在区域id")
    private Integer regionId;

    @CompareField(value = "园区地址")
    @ApiModelProperty(value = "园区地址")
    private String address;

    @CompareField(value = "园区所占面积")
    @ApiModelProperty(value = "园区所占面积")
    private BigDecimal area;
    ......
}

通过value表明修改字段的中文含义。

3、编写工具类

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

public class ObjectComparator {
    public static Map<String, String> compare(Object oldObj, Object newObj) {
        Map<String, String> result = new HashMap<>();
        try {
            // 获取所有字段
            Field[] fields = oldObj.getClass().getDeclaredFields();
            // 遍历所有字段
            for (Field field : fields) {
                // 如果字段被 @CompareField 注解标注
                if (field.isAnnotationPresent(CompareField.class)) {
                    // 获取字段的中文名
                    String fieldName = field.getAnnotation(CompareField.class).value();
                    // 设置字段可访问
                    field.setAccessible(true);
                    // 获取字段的旧值和新值
                    Object oldValue = field.get(oldObj);
                    Object newValue = field.get(newObj);
                    // 如果值不相等
                    if (!Objects.equals(oldValue, newValue)) {
                        //BigDecimal单独判断
                        if (oldValue instanceof BigDecimal) {
                            BigDecimal oldV = (BigDecimal) oldValue;
                            BigDecimal newV = (BigDecimal) newValue;
                            if (oldV.compareTo(newV) == 0) {
                                continue;
                            }
                        }
                        // 将字段名和值添加到结果中
                        result.put(fieldName, "旧值:" + oldValue + " ~ 新值:" + newValue);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}

4、执行调用

String detail = "修改楼宇:";
Map<String, String> compare = ObjectComparator.compare(buildingPark1, bcBuildingPark);
detail += compare.toString();
recordService.addBcBuildingParkRecord(bcBuildingPark,StatusConstant.PARK_UPDATE, detail);
return AjaxResult.success("修改楼宇园区成功");

5、结果展示 image.png