JAVA 通用寻找对象间差异的所有字段
- 2020 年 4 月 1 日
- 笔记
最近在做某个项目中,需要查找多个属性间不同的字段,但这些属性很多,一个一个的字段比较,很折腾,所以就自己写了一个快速的框架. 1.定义需要对比的结果,有新增,变更,删除,无变化四种结果
public enum CompareStatus { /** * 标记新数据 */ NEW, /** * 标记变更数据 */ CHANGE, /** * 标记删除数据 */ DELETE, /** * 标记没有变更 */ NO_CHANGE; }
- 定义对比的结果类
@AllArgsConstructor @NoArgsConstructor @Data public class CompareResult { /** * 差异的结果属性 */ private String propertyName; /** * 原来的属性 */ private Object originalValue; /** * 当前的属性 */ private Object currentValue; }
- 具体对比的结果方法及实现
@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; } }
- 测试具体调用的方法
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());
自此,就能快速的获取两个对象的差异,面不需要一个一个的比较