一个自己写的判断2个相同对象的属性值差异的工具类
在后台管理系统中经常会有需要记录用户操作日志的需求,其中需要最好能记录用户修改了哪些字段的数据(变更前,变更后),这个时候就需要抽取一个工具的类来处理这件事。
20180105进行优化升级:1、增加对基本类型的集合的对比。2、优化反射的缓存。3、增加dto+集合的混合对比方法。
结果样例:
[{ "column": "name", "difference": { "newValue": "李四", "oldValue": "张三" } }, { "column": "arr", "difference": { "newValue": [{ "column": "delete", "difference": { "newValue": null, "oldValue": [1] } }, { "column": "add", "difference": { "newValue": [4], "oldValue": null } } ], "oldValue": null } } ]
工具类:
1 import java.io.Serializable; 2 import java.lang.reflect.Field; 3 import java.lang.reflect.InvocationTargetException; 4 import java.lang.reflect.Method; 5 import java.math.BigDecimal; 6 import java.util.ArrayList; 7 import java.util.Collection; 8 import java.util.HashMap; 9 import java.util.HashSet; 10 import java.util.List; 11 import java.util.Map; 12 import java.util.Set; 13 import java.util.regex.Matcher; 14 import java.util.regex.Pattern; 15 16 import org.reflections.ReflectionUtils; 17 18 import com.alibaba.fastjson.JSON; 19 import com.alibaba.fastjson.serializer.SerializerFeature; 20 21 import lombok.AllArgsConstructor; 22 import lombok.Builder; 23 import lombok.Getter; 24 import lombok.NoArgsConstructor; 25 import lombok.Setter; 26 import lombok.extern.slf4j.Slf4j; 27 28 /** 29 * 比较2个对象的值的不同的情况 30 * 31 * 注意:对声明值比较类为基本类型的但传入非基本类型的话不保证程序和数据的正确性。 32 * 33 * 目前支持的比较类型有: 34 * 1、普通dto(不包含复杂对象)的比较 35 * 可用的方法有: 36 * {@link CompareDifferenceUtil#isDifference(Object, Object)} 37 * {@link CompareDifferenceUtil#isDifferenceSelective(Object, Object)} 38 * {@link CompareDifferenceUtil#compare(Object, Object)} 39 * {@link CompareDifferenceUtil#compareSelective(Object, Object)} 40 * {@link CompareDifferenceUtil#getDiffernceList(Object, Object)} 41 * {@link CompareDifferenceUtil#getDiffernceListSelective(Object, Object)} 42 * 2、普通基本类型的集合的比较 43 * 可用的方法有: 44 * {@link CompareDifferenceUtil#isDifference(Collection, Collection)} 45 * {@link CompareDifferenceUtil#compareCollection(Collection, Collection)} 46 * {@link CompareDifferenceUtil#compareCollectionSelective(Collection, Collection)} 47 * 3、普通dto(不包含复杂对象) + 普通基本类型的集合的比较 48 * 可用的方法有: 49 * {@link CompareDifferenceUtil#compare(Object, Object, CompareCollectionDto...)} 50 * {@link CompareDifferenceUtil#compareSelective(Object, Object, CompareCollectionDto...)} 51 * 4、主从一对一的比较 52 * 可用的方法有: 53 * {@link CompareDifferenceUtil#compareMainAndDetail(Object, Object, String, Object, Object)} 54 * {@link CompareDifferenceUtil#compareMainAndDetailSelective(Object, Object, String, Object, Object)} 55 * 56 * 57 * @author yangzhilong 58 */ 59 @Slf4j 60 public class CompareDifferenceUtil { 61 private static final String ADD = "add"; 62 private static final String UPDATE = "update"; 63 private static final String DELETE = "delete"; 64 private static final Set<String> ignoreFileds = new HashSet<>(5); 65 66 private static final Map<String,Set<Field>> fieldCache = new HashMap<>(); 67 private static final Map<String,Set<Method>> methodCache = new HashMap<>(); 68 69 static { 70 ignoreFileds.add("serialVersionUID"); 71 ignoreFileds.add("createBy"); 72 ignoreFileds.add("createTime"); 73 ignoreFileds.add("updateBy"); 74 ignoreFileds.add("updateTime"); 75 } 76 77 /** 78 * 比较2个对象是否有差异 79 * @param oldObj 80 * @param newObj 81 * @return 82 */ 83 public static boolean isDifference(Object oldObj, Object newObj) { 84 return !getDiffernceList(oldObj, newObj, true, false).isEmpty(); 85 } 86 87 /** 88 * 比较2个对象是否有差异(新增中的属性为null的话跳过比较该属性) 89 * @param oldObj 90 * @param newObj 91 * @return 92 */ 93 public static boolean isDifferenceSelective(Object oldObj, Object newObj) { 94 return !getDiffernceList(oldObj, newObj, true, true).isEmpty(); 95 } 96 97 /** 98 * 比较2个集合是否有差异(基本类型) 99 * @param oldCollection 100 * @param newCollection 101 * @return 102 */ 103 public static <T> boolean isDifference(Collection<T> oldCollection, Collection<T> newCollection) { 104 return !compareCollectionList(oldCollection, newCollection).isEmpty(); 105 } 106 107 /** 108 * 得到变化的列的数据 109 * @param oldObj 110 * @param newObj 111 * @return 112 */ 113 public static List<DifferenceWapper> getDiffernceList(Object oldObj, Object newObj) { 114 return getDiffernceList(oldObj, newObj, false, false); 115 } 116 117 /** 118 * 得到变化的列的数据(新增中的属性为null的话跳过比较该属性) 119 * @param oldObj 120 * @param newObj 121 * @return 122 */ 123 public static List<DifferenceWapper> getDiffernceListSelective(Object oldObj, Object newObj) { 124 return getDiffernceList(oldObj, newObj, false, true); 125 } 126 127 /** 128 * 比较主从对象的复杂类型的数据(主从一对一关系) 129 * @param oldMainObj 主对象的老对象 130 * @param newMainObj 助对象的新对象 131 * @param detailAttrName 主对象中detail的属性名称 132 * @param oldDetailObj 明细对象的老对象(复杂类型的对象,但非集合) 133 * @param newDetailObj 明细对象的新对象(复杂类型的对象,但非集合) 134 * @return 135 */ 136 public static String compareMainAndDetail(Object oldMainObj, Object newMainObj, String detailAttrName, Object oldDetailObj, Object newDetailObj) { 137 return aggregateDataAndConvertToJson(getDiffernceList(oldMainObj, newMainObj), detailAttrName , getDiffernceList(oldDetailObj, newDetailObj)); 138 } 139 140 /** 141 * 比较主从对象的复杂类型的数据(主从一对一关系) 142 * @param oldMainObj 主对象的老对象 143 * @param newMainObj 助对象的新对象 144 * @param detailAttrName 主对象中detail的属性名称 145 * @param oldDetailObj 明细对象的老对象(复杂类型的对象,但非集合) 146 * @param newDetailObj 明细对象的新对象(复杂类型的对象,但非集合) 147 * @return 148 */ 149 public static String compareMainAndDetailSelective(Object oldMainObj, Object newMainObj, String detailAttrName, Object oldDetailObj, Object newDetailObj) { 150 return aggregateDataAndConvertToJson(getDiffernceListSelective(oldMainObj, newMainObj), detailAttrName , getDiffernceListSelective(oldDetailObj, newDetailObj)); 151 } 152 153 /** 154 * 得到2个相同对象的相同字段的不同的值 155 * 156 * @param oldObj 变更前对象,不能为null 157 * @param newObj 变更后对象,不能为null 158 * @return 159 */ 160 public static String compare(Object oldObj, Object newObj) { 161 List<DifferenceWapper> result = getDiffernceList(oldObj, newObj); 162 if(!result.isEmpty()) { 163 return JSON.toJSONString(result, SerializerFeature.WriteMapNullValue); 164 } 165 return null; 166 } 167 168 /** 169 * 得到2个相同对象的相同字段的不同的值,newObj中有属性为null,就跳过这个属性 170 * 171 * @param oldObj 变更前对象,不能为null 172 * @param newObj 变更后对象,不能为null 173 * @return 174 */ 175 public static String compareSelective(Object oldObj, Object newObj) { 176 List<DifferenceWapper> result = getDiffernceListSelective(oldObj, newObj); 177 if(!result.isEmpty()) { 178 return JSON.toJSONString(result, SerializerFeature.WriteMapNullValue); 179 } 180 return null; 181 } 182 183 /** 184 * 得到2个对象以及相关list的差异 185 * @param <T> 186 * @param oldObj 187 * @param newObj 188 * @param array 多个基本类型的集合的包装类 189 * @return 190 */ 191 @SuppressWarnings("unchecked") 192 public static <T> String compare(Object oldObj, Object newObj, CompareCollectionDto<T>... array) { 193 return baseCompare(oldObj, newObj, false, array); 194 } 195 196 /** 197 * 得到2个对象以及相关list的差异,如果有新list集合为空,则忽略此属性 198 * @param <T> 199 * @param oldObj 200 * @param newObj 201 * @param array 多个基本类型的集合的包装类 202 * @return 203 */ 204 @SuppressWarnings("unchecked") 205 public static <T> String compareSelective(Object oldObj, Object newObj, CompareCollectionDto<T>... array) { 206 return baseCompare(oldObj, newObj, true, array); 207 } 208 209 /** 210 * 比较2个字符串集合的差异(只支持基本类型) 211 * @param <T> 212 * @param oldCollection 213 * @param newCollection 214 * @return 215 */ 216 public static <T> String compareCollection(Collection<T> oldCollection, Collection<T> newCollection) { 217 List<DifferenceWapper> result = compareCollectionList(oldCollection, newCollection); 218 if(result.isEmpty()) { 219 return null; 220 } 221 return JSON.toJSONString(result, SerializerFeature.WriteMapNullValue); 222 } 223 224 /** 225 * 比较2个字符串集合的差异(只支持基本类型),如果newCollection为null,则忽略比较 226 * @param <T> 227 * @param oldCollection 228 * @param newCollection 229 * @return 230 */ 231 public static <T> String compareCollectionSelective(Collection<T> oldCollection, Collection<T> newCollection) { 232 List<DifferenceWapper> result = compareCollectionListSelective(oldCollection, newCollection); 233 if(result.isEmpty()) { 234 return null; 235 } 236 return JSON.toJSONString(result, SerializerFeature.WriteMapNullValue); 237 } 238 239 /** 240 * 基本的检查 241 * @param oldObj 242 * @param newObj 243 * @param selective 244 * @param array 245 * @return 246 */ 247 @SuppressWarnings("unchecked") 248 private static <T> String baseCompare(Object oldObj, Object newObj, boolean selective, CompareCollectionDto<T>... array) { 249 if(null==array || array.length == 0) { 250 throw new RuntimeException("集合对象的数组不能为空"); 251 } 252 List<DifferenceWapper> result = getDiffernceList(oldObj, newObj, false, selective); 253 for(CompareCollectionDto<T> dto : array) { 254 List<DifferenceWapper> cr = null; 255 if(selective) { 256 cr = compareCollectionListSelective(dto.getOldCollection(), dto.getNewCollection()); 257 } else { 258 cr = compareCollectionList(dto.getOldCollection(), dto.getNewCollection()); 259 } 260 261 if(!cr.isEmpty()) { 262 DifferenceWapper wapper = DifferenceWapper.builder().column(dto.getFiledName()) 263 .difference(Difference.builder().newValue(cr).build()).build(); 264 result.add(wapper); 265 } 266 } 267 if(!result.isEmpty()) { 268 return JSON.toJSONString(result, SerializerFeature.WriteMapNullValue); 269 } 270 return null; 271 } 272 273 /** 274 * 275 * @param oldObj 276 * @param newObj 277 * @param onlyCheck 是否仅校验(遇到不同则立刻返回) 278 * @param selective true代表如果newObj的属性的值为null则跳过该属性比较 279 * @return 280 */ 281 private static List<DifferenceWapper> getDiffernceList(Object oldObj, Object newObj, boolean onlyCheck, boolean selective) { 282 List<DifferenceWapper> result = new ArrayList<>(); 283 284 // 是否是创建类型的比较 285 boolean isCreate = false; 286 if(oldObj == null) { 287 isCreate = true; 288 } else { 289 if(null == newObj) { 290 throw new RuntimeException("更改后的对象不能为null"); 291 } 292 } 293 if(!isCreate && !newObj.getClass().equals(oldObj.getClass())) { 294 throw new RuntimeException("两个需要比较的对象必须为同一类型"); 295 } 296 // 同一个对象就没必要对比了 297 if(oldObj == newObj) { 298 return result; 299 } 300 301 Set<Field> fields = getField(newObj.getClass()); 302 Set<Method> methods = getMethod(newObj.getClass()); 303 304 if(null != fields && !fields.isEmpty()) { 305 String methodName = null; 306 String fieldName = null; 307 for(Field field : fields) { 308 if(ignoreFileds.contains(field.getName())) { 309 continue; 310 } 311 fieldName = field.getName(); 312 methodName = "get".concat(fieldName.substring(0, 1).toUpperCase()).concat(fieldName.substring(1)); 313 314 Method method = filterMethod(methods, methodName); 315 if(null == method) { 316 // 是小boolean类型则需要特殊处理 317 if("boolean".equals(field.getType().getTypeName())) { 318 if(fieldName.startsWith("is")) { 319 // 如果第三位是大写 320 boolean upper = isUpperString(fieldName.substring(2, 3)); 321 if(upper) { 322 methodName = fieldName; 323 } else { 324 methodName = "is".concat(fieldName.substring(0, 1).toUpperCase()).concat(fieldName.substring(1)); 325 } 326 } else { 327 methodName = "is".concat(fieldName.substring(0, 1).toUpperCase()).concat(fieldName.substring(1)); 328 } 329 method = filterMethod(methods, methodName); 330 } 331 if(null == method) { 332 continue; 333 } 334 } 335 try { 336 Object oldValue = null; 337 if(!isCreate) { 338 oldValue = method.invoke(oldObj); 339 } 340 Object newValue = method.invoke(newObj); 341 if(null == oldValue) { 342 if(null != newValue) { 343 result.add(DifferenceWapper.builder().column(fieldName).difference(Difference.builder().newValue(newValue).oldValue(oldValue).build()).build()); 344 } 345 } else { 346 if(null != newValue) { 347 // 处理0.0和0的不同 348 if(newValue instanceof BigDecimal){ 349 BigDecimal newValue1 = (BigDecimal) newValue; 350 BigDecimal oldValue1 = (BigDecimal) oldValue; 351 if(newValue1.compareTo(oldValue1) != 0){ 352 result.add(DifferenceWapper.builder().column(fieldName).difference(Difference.builder().newValue(newValue).oldValue(oldValue).build()).build()); 353 } 354 } else if(!oldValue.equals(newValue)) { 355 result.add(DifferenceWapper.builder().column(fieldName).difference(Difference.builder().newValue(newValue).oldValue(oldValue).build()).build()); 356 } 357 } else { 358 if(!selective) { 359 result.add(DifferenceWapper.builder().column(fieldName).difference(Difference.builder().newValue(newValue).oldValue(oldValue).build()).build()); 360 } 361 } 362 } 363 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 364 log.error("反射调用get方法异常", e); 365 throw new RuntimeException(e); 366 } 367 /** 368 * 如果仅仅校验是否不同,则提前返回 369 */ 370 if(onlyCheck && !result.isEmpty()) { 371 return result; 372 } 373 } 374 } 375 return result; 376 } 377 378 /** 379 * 获取类的所有字段 380 * @param type 381 * @return 382 */ 383 @SuppressWarnings("unchecked") 384 private static Set<Field> getField(Class<?> type) { 385 String className = type.getName(); 386 if(fieldCache.get(className) == null || fieldCache.get(className).isEmpty()) { 387 synchronized (className) { 388 if(fieldCache.get(className) == null || fieldCache.get(className).isEmpty()) { 389 fieldCache.put(className, ReflectionUtils.getAllFields(type)); 390 } 391 } 392 } 393 return fieldCache.get(className); 394 } 395 396 /** 397 * 获取类的所有方法 398 * @param type 399 * @return 400 */ 401 @SuppressWarnings("unchecked") 402 private static Set<Method> getMethod(Class<?> type) { 403 String className = type.getName(); 404 if(methodCache.get(className) == null || methodCache.get(className).isEmpty()) { 405 synchronized (className) { 406 if(methodCache.get(className) == null || methodCache.get(className).isEmpty()) { 407 methodCache.put(className, ReflectionUtils.getAllMethods(type)); 408 } 409 } 410 } 411 return methodCache.get(className); 412 } 413 414 /** 415 * 比较2个字符串集合的差异(只支持基本类型) 416 * @param <T> 417 * @param oldCollection 418 * @param newCollection 419 * @return 420 */ 421 private static <T> List<DifferenceWapper> compareCollectionList(Collection<T> oldCollection, Collection<T> newCollection) { 422 String flag = UPDATE; 423 if(null==oldCollection || oldCollection.isEmpty()) { 424 if(null==newCollection || newCollection.isEmpty()) { 425 throw new RuntimeException("两个需要比较的集合不能都为空"); 426 } 427 flag = ADD; 428 } else { 429 if(null==newCollection || newCollection.isEmpty()) { 430 flag = DELETE; 431 } 432 } 433 434 if(ADD.equals(flag)) { 435 return compareCollectionAdd(newCollection); 436 } else if(DELETE.equals(flag)) { 437 return compareCollectionDelete(oldCollection); 438 } else { 439 return compareCollectionUpdate(oldCollection, newCollection); 440 } 441 } 442 443 /** 444 * 比较2个字符串集合的差异(只支持基本类型),如果newCollection为null,则忽略比较 445 * @param <T> 446 * @param oldCollection 447 * @param newCollection 448 * @return 449 */ 450 private static <T> List<DifferenceWapper> compareCollectionListSelective(Collection<T> oldCollection, Collection<T> newCollection) { 451 String flag = UPDATE; 452 if(null==oldCollection || oldCollection.isEmpty()) { 453 if(null==newCollection || newCollection.isEmpty()) { 454 return new ArrayList<>(); 455 } 456 flag = ADD; 457 } else { 458 if(null==newCollection || newCollection.isEmpty()) { 459 return new ArrayList<>(); 460 } 461 } 462 463 if(ADD.equals(flag)) { 464 return compareCollectionAdd(newCollection); 465 } else if(DELETE.equals(flag)) { 466 return compareCollectionDelete(oldCollection); 467 } else { 468 return compareCollectionUpdate(oldCollection, newCollection); 469 } 470 } 471 472 /** 473 * 新增 474 * @param newCollection 475 * @return 476 */ 477 private static <T> List<DifferenceWapper> compareCollectionAdd(Collection<T> newCollection) { 478 List<DifferenceWapper> result = new ArrayList<>(1); 479 DifferenceWapper diff = new DifferenceWapper(); 480 Difference difference = new Difference(); 481 difference.setNewValue(newCollection); 482 diff.setColumn("add"); 483 diff.setDifference(difference); 484 result.add(diff); 485 return result; 486 } 487 488 /** 489 * 删除 490 * @param oldCollection 491 * @return 492 */ 493 private static <T> List<DifferenceWapper> compareCollectionDelete(Collection<T> oldCollection) { 494 List<DifferenceWapper> result = new ArrayList<>(1); 495 DifferenceWapper diff = new DifferenceWapper(); 496 Difference difference = new Difference(); 497 difference.setOldValue(oldCollection); 498 diff.setColumn("delete"); 499 diff.setDifference(difference); 500 result.add(diff); 501 return result; 502 } 503 504 /** 505 * 更新 506 * @param oldCollection 507 * @param newCollection 508 * @return 509 */ 510 private static <T> List<DifferenceWapper> compareCollectionUpdate(Collection<T> oldCollection, Collection<T> newCollection) { 511 List<DifferenceWapper> ret = new ArrayList<>(); 512 513 Set<T> result = new HashSet<>(); 514 Set<T> oldSet = new HashSet<>(); 515 oldSet.addAll(oldCollection); 516 Set<T> newSet = new HashSet<>(); 517 newSet.addAll(newCollection); 518 519 //取交集 520 result.addAll(oldCollection); 521 result.retainAll(newCollection); 522 523 //没有变更 524 if(result.size()==newSet.size() && result.size()==oldSet.size()) { 525 return ret; 526 } 527 528 //被删除的 529 //取差集 530 oldSet.removeAll(result); 531 532 //新增的 533 //取差集 534 newSet.removeAll(result); 535 536 if(!oldSet.isEmpty()) { 537 DifferenceWapper diff = new DifferenceWapper(); 538 Difference difference = new Difference(); 539 difference.setOldValue(oldSet); 540 diff.setColumn("delete"); 541 diff.setDifference(difference); 542 ret.add(diff); 543 } 544 if(!newSet.isEmpty()) { 545 DifferenceWapper diff = new DifferenceWapper(); 546 Difference difference = new Difference(); 547 difference.setNewValue(newSet); 548 diff.setColumn("add"); 549 diff.setDifference(difference); 550 ret.add(diff); 551 } 552 553 return ret; 554 } 555 556 /** 557 * 过滤方法 558 * @param methods 559 * @param methodName 560 * @return 561 */ 562 private static Method filterMethod(Set<Method> methods, String methodName) { 563 if(null != methods && !methods.isEmpty()) { 564 for(Method method : methods) { 565 if(method.getName().equals(methodName)) { 566 return method; 567 } 568 } 569 } 570 return null; 571 } 572 573 /** 574 * 匹配是否是大写字母 575 * @param str 576 * @return 577 */ 578 private static boolean isUpperString(String str) { 579 Pattern p = Pattern.compile("[A-Z]"); 580 Matcher matcher = p.matcher(str); 581 return matcher.matches(); 582 } 583 584 /** 585 * 聚合主和明细数据的变更记录 586 * @param main 587 * @param attrName 显示在主对象里的属性 588 * @param detail 明细对象的属性差异的list 589 */ 590 private static List<DifferenceWapper> aggregateData(List<DifferenceWapper> main, String attrName, List<DifferenceWapper> detail) { 591 if(null != detail && !detail.isEmpty()) { 592 if(null == main || main.isEmpty()) { 593 main = new ArrayList<>(1); 594 } 595 main.add(DifferenceWapper.builder().column(attrName).difference(Difference.builder().newValue(detail).build()).build()); 596 } 597 return main; 598 } 599 600 /** 601 * 聚合主和明细数据的变更记录并转换成json 602 * @param main 603 * @param attrName 显示在主对象里的属性 604 * @param detail 明细对象的属性差异的list 605 */ 606 private static String aggregateDataAndConvertToJson(List<DifferenceWapper> main, String attrName, List<DifferenceWapper> detail) { 607 List<DifferenceWapper> result = aggregateData(main, attrName, detail); 608 if(null!=result && !result.isEmpty()) { 609 return JSON.toJSONString(result, SerializerFeature.WriteMapNullValue); 610 } 611 return null; 612 } 613 614 @Getter 615 @Setter 616 @Builder 617 @NoArgsConstructor 618 @AllArgsConstructor 619 static class DifferenceWapper implements Serializable { 620 private static final long serialVersionUID = -3369182406683473741L; 621 private String column; 622 private Difference difference; 623 } 624 625 @Getter 626 @Setter 627 @Builder 628 @NoArgsConstructor 629 @AllArgsConstructor 630 static class Difference implements Serializable{ 631 private static final long serialVersionUID = 2478199484126795290L; 632 633 private Object oldValue; 634 private Object newValue; 635 } 636 637 }
辅助DTO类:
1 package com.longge.utils; 2 3 import java.io.Serializable; 4 import java.util.Collection; 5 6 import lombok.AllArgsConstructor; 7 import lombok.Builder; 8 import lombok.Getter; 9 import lombok.NoArgsConstructor; 10 import lombok.Setter; 11 12 /** 13 * 集合类型的属性的比较包装类 14 * @author yangzhilong 15 * 16 * @param <T> 17 */ 18 @Getter 19 @Setter 20 @Builder 21 @NoArgsConstructor 22 @AllArgsConstructor 23 public class CompareCollectionDto<T> implements Serializable { 24 private static final long serialVersionUID = -4977550220859897197L; 25 private String filedName; 26 private Collection<T> oldCollection; 27 private Collection<T> newCollection; 28 }
测试类:
1 package com.tomato.boss.common; 2 3 import java.util.Arrays; 4 import java.util.List; 5 6 import com.tomato.boss.common.utils.CompareCollectionDto; 7 import com.tomato.boss.common.utils.CompareDifferenceUtil; 8 9 import lombok.Getter; 10 import lombok.Setter; 11 12 public class CompareDifferenceUtilTest { 13 public static void main(String[] args) { 14 Dto dto1 = new Dto(); 15 Dto dto2 = new Dto(); 16 17 dto1.setAge(10); 18 dto1.setDelete(false); 19 dto1.setFlag(false); 20 dto1.setIssTrue(false); 21 dto1.setName("张三"); 22 dto1.setSize(10); 23 dto1.setTrue(false); 24 dto1.setCreateBy("xxx"); 25 dto1.setType("1"); 26 27 dto2.setAge(15); 28 dto2.setDelete(true); 29 dto2.setFlag(true); 30 dto2.setIssTrue(true); 31 dto2.setName("李四"); 32 dto2.setSize(20); 33 dto2.setTrue(true); 34 dto2.setCreateBy("yyyyy"); 35 dto2.setType("2"); 36 37 List<Integer> oldList = Arrays.asList(1,2,3); 38 List<Integer> newList = Arrays.asList(2,3,4); 39 40 dto1.setArr(oldList); 41 dto2.setArr(newList); 42 43 System.out.println(CompareDifferenceUtil.isDifference(dto1, dto2)); 44 System.out.println(CompareDifferenceUtil.compare(dto1, dto2)); 45 System.out.println(CompareDifferenceUtil.isDifference(oldList, newList)); 46 System.out.println(CompareDifferenceUtil.compareCollection(oldList, newList)); 47 48 CompareCollectionDto<Integer> dto = new CompareCollectionDto<>("arr",oldList,newList); 49 CompareCollectionDto<Integer> dtox = new CompareCollectionDto<>("arry",oldList,newList); 50 51 System.out.println(CompareDifferenceUtil.compare(dto1, dto2, dto, dtox)); 52 53 Children c1 = new Children(); 54 c1.setCname("张三"); 55 56 Children c2 = new Children(); 57 c2.setCname("李四"); 58 59 System.out.println(CompareDifferenceUtil.compareMainAndDetail(dto1, dto2, "child", c1, c2)); 60 } 61 62 63 @Getter 64 @Setter 65 public static class Dto extends P{ 66 private boolean isTrue; 67 private boolean issTrue; 68 private boolean delete; 69 private Boolean flag; 70 private String name; 71 private Integer age; 72 private int size; 73 private String createBy; 74 private List<Integer> arr; 75 } 76 77 @Getter 78 @Setter 79 public static class P { 80 private String type; 81 } 82 83 @Getter 84 @Setter 85 public static class Children { 86 private String cname; 87 } 88 }
测试结果比较对象的(JSON格式的字符串):
[{ "column": "name", "difference": { "newValue": "李四", "oldValue": "张三" } }, { "column": "delete", "difference": { "newValue": true, "oldValue": false } }, { "column": "age", "difference": { "newValue": 15, "oldValue": 10 } }, { "column": "issTrue", "difference": { "newValue": true, "oldValue": false } }, { "column": "isTrue", "difference": { "newValue": true, "oldValue": false } }, { "column": "flag", "difference": { "newValue": true, "oldValue": false } }, { "column": "size", "difference": { "newValue": 20, "oldValue": 10 } } ]
比较集合的:
1 [{ 2 "column": "delete", 3 "difference": { 4 "newValue": null, 5 "oldValue": 1 6 } 7 }, { 8 "column": "add", 9 "difference": { 10 "newValue": 4, 11 "oldValue": null 12 } 13 } 14 ]
比较dto+集合的:
1 [{ 2 "column": "name", 3 "difference": { 4 "newValue": "李四", 5 "oldValue": "张三" 6 } 7 }, { 8 "column": "arr", 9 "difference": { 10 "newValue": [{ 11 "column": "delete", 12 "difference": { 13 "newValue": null, 14 "oldValue": [1] 15 } 16 }, { 17 "column": "add", 18 "difference": { 19 "newValue": [4], 20 "oldValue": null 21 } 22 } 23 ], 24 "oldValue": null 25 } 26 } 27 ]
比较dto+子dto的:
1 [ 2 { 3 "column": "name", 4 "difference": { 5 "newValue": "李四", 6 "oldValue": "张三" 7 } 8 }, { 9 "column": "delete", 10 "difference": { 11 "newValue": true, 12 "oldValue": false 13 } 14 }, { 15 "column": "child", 16 "difference": { 17 "newValue": [{ 18 "column": "cname", 19 "difference": { 20 "newValue": "李四", 21 "oldValue": "张三" 22 } 23 } 24 ], 25 "oldValue": null 26 } 27 } 28 ]