|
|
@@ -2,12 +2,12 @@ package com.hz.pm.api.projectdeclared.utils; |
|
|
|
|
|
|
|
import cn.hutool.core.bean.BeanUtil; |
|
|
|
import cn.hutool.core.collection.CollUtil; |
|
|
|
import cn.hutool.core.map.MapUtil; |
|
|
|
import cn.hutool.core.util.ArrayUtil; |
|
|
|
import cn.hutool.core.util.ObjUtil; |
|
|
|
import lombok.Builder; |
|
|
|
import lombok.Data; |
|
|
|
|
|
|
|
import java.io.Serializable; |
|
|
|
import java.util.*; |
|
|
|
|
|
|
|
/** |
|
|
@@ -18,20 +18,18 @@ import java.util.*; |
|
|
|
* @author WendyYang |
|
|
|
* @since 10:27 2024/8/6 |
|
|
|
*/ |
|
|
|
public class BeanDiffUtil { |
|
|
|
public final class BeanDiffUtil { |
|
|
|
|
|
|
|
private BeanDiffUtil() { |
|
|
|
} |
|
|
|
|
|
|
|
@Data |
|
|
|
@Builder |
|
|
|
public static class FieldDiff implements Serializable { |
|
|
|
|
|
|
|
private static final long serialVersionUID = -9003132377177378460L; |
|
|
|
public static class FieldDiff { |
|
|
|
|
|
|
|
private String fieldName; |
|
|
|
|
|
|
|
private String fileType; |
|
|
|
private String fieldType; |
|
|
|
|
|
|
|
private Object oldValue; |
|
|
|
|
|
|
@@ -42,88 +40,68 @@ public class BeanDiffUtil { |
|
|
|
/** |
|
|
|
* 比较两个对象的不同属性值,包括嵌套的对象属性。 |
|
|
|
* |
|
|
|
* @param obj1 第一个对象 |
|
|
|
* @param obj2 第二个对象 |
|
|
|
* @return 返回一个 Map,其中 key 是不同属性的名称,value 是一个包含两个值的数组,第一个值来自 obj1,第二个值来自 obj2 |
|
|
|
*/ |
|
|
|
private static List<FieldDiff> diff(Object obj1, Object obj2, boolean diffSameField, String... ignoreFields) { |
|
|
|
Map<String, Object> map1 = BeanUtil.beanToMap(obj1); |
|
|
|
Map<String, Object> map2 = BeanUtil.beanToMap(obj2); |
|
|
|
if (ArrayUtil.isNotEmpty(ignoreFields)) { |
|
|
|
for (String ignoreField : ignoreFields) { |
|
|
|
map2.remove(ignoreField); |
|
|
|
map1.remove(ignoreField); |
|
|
|
* @param oldObj oldObj |
|
|
|
* @param newObj newObj |
|
|
|
* @param diffSame 是否只对比相同属性 |
|
|
|
* @param ignores 忽略比较的字段 |
|
|
|
* @return 对比结果 |
|
|
|
**/ |
|
|
|
public static List<FieldDiff> diff(Object oldObj, Object newObj, boolean diffSame, String... ignores) { |
|
|
|
Map<String, Object> oldObjMap = BeanUtil.beanToMap(oldObj); |
|
|
|
Map<String, Object> newObjMap = BeanUtil.beanToMap(newObj); |
|
|
|
if (ArrayUtil.isNotEmpty(ignores)) { |
|
|
|
for (String ignore : ignores) { |
|
|
|
newObjMap.remove(ignore); |
|
|
|
oldObjMap.remove(ignore); |
|
|
|
} |
|
|
|
} |
|
|
|
// 创建结果 Map |
|
|
|
List<FieldDiff> result = new ArrayList<>(); |
|
|
|
|
|
|
|
// 获取两个 Map 的 keySet |
|
|
|
Set<String> keys1 = map1.keySet(); |
|
|
|
Set<String> keys2 = map2.keySet(); |
|
|
|
Set<String> oldObjKeys = oldObjMap.keySet(); |
|
|
|
Set<String> newObjKeys = newObjMap.keySet(); |
|
|
|
|
|
|
|
// 计算不同的属性 |
|
|
|
Collection<String> diffKeys = CollUtil.disjunction(keys1, keys2); |
|
|
|
Collection<String> diffKeys = CollUtil.disjunction(oldObjKeys, newObjKeys); |
|
|
|
|
|
|
|
if (!diffSameField) { |
|
|
|
if (!diffSame) { |
|
|
|
// 输出不同的属性及其值 |
|
|
|
for (String key : diffKeys) { |
|
|
|
Object oldValue = map1.getOrDefault(key, null); |
|
|
|
Object newValue = map2.getOrDefault(key, null); |
|
|
|
Object oldVal = oldObjMap.get(key); |
|
|
|
Object newVal = newObjMap.get(key); |
|
|
|
result.add(FieldDiff.builder() |
|
|
|
.fieldName(key) |
|
|
|
.fileType((oldValue == null ? newValue.getClass() : oldValue.getClass()).getTypeName()) |
|
|
|
.oldValue(oldValue) |
|
|
|
.newValue(newValue) |
|
|
|
.fieldType((oldObj == null ? newVal.getClass() : oldVal.getClass()).getTypeName()) |
|
|
|
.oldValue(oldVal) |
|
|
|
.newValue(newVal) |
|
|
|
.build()); |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// 输出相同的属性,但是值不同 |
|
|
|
Collection<String> commonKeys = CollUtil.intersection(keys1, keys2); |
|
|
|
for (String key : commonKeys) { |
|
|
|
Object value1 = map1.get(key); |
|
|
|
Object value2 = map2.get(key); |
|
|
|
if (value1 == null && value2 == null) { |
|
|
|
Collection<String> sameKeys = CollUtil.intersection(oldObjKeys, newObjKeys); |
|
|
|
for (String key : sameKeys) { |
|
|
|
Object oldVal = oldObjMap.get(key); |
|
|
|
Object newVal = newObjMap.get(key); |
|
|
|
if (oldVal == null && newVal == null) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
Class<?> valueClass = value1 == null ? value2.getClass() : value1.getClass(); |
|
|
|
Class<?> clazz = oldVal == null ? newVal.getClass() : oldVal.getClass(); |
|
|
|
oldVal = MapUtil.get(oldObjMap, key, clazz); |
|
|
|
newVal = MapUtil.get(newObjMap, key, clazz); |
|
|
|
// 如果是嵌套对象,则递归比较 |
|
|
|
if (!BeanUtil.isBean(valueClass) && !ObjUtil.equals(value1, value2)) { |
|
|
|
Object oldValue = map1.getOrDefault(key, null); |
|
|
|
Object newValue = map2.getOrDefault(key, null); |
|
|
|
if (!BeanUtil.isBean(clazz) && ObjUtil.notEqual(oldVal, newVal)) { |
|
|
|
result.add(FieldDiff.builder() |
|
|
|
.fieldName(key) |
|
|
|
.fileType((oldValue == null ? newValue.getClass() : oldValue.getClass()).getTypeName()) |
|
|
|
.oldValue(oldValue) |
|
|
|
.newValue(newValue) |
|
|
|
.fieldType(clazz.getTypeName()) |
|
|
|
.oldValue(oldVal) |
|
|
|
.newValue(newVal) |
|
|
|
.build()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return result; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 比较两个对象的不同属性值,包括嵌套的对象属性。 |
|
|
|
* |
|
|
|
* @param obj1 第一个对象 |
|
|
|
* @param obj2 第二个对象 |
|
|
|
* @return 返回一个 Map,其中 key 是不同属性的名称,value 是一个包含两个值的数组,第一个值来自 obj1,第二个值来自 obj2 |
|
|
|
*/ |
|
|
|
public static List<FieldDiff> diffSameField(Object obj1, Object obj2, String... ignoreFields) { |
|
|
|
return diff(obj1, obj2, true, ignoreFields); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 比较两个对象的不同属性值,包括嵌套的对象属性。 |
|
|
|
* |
|
|
|
* @param obj1 第一个对象 |
|
|
|
* @param obj2 第二个对象 |
|
|
|
* @return 返回一个 Map,其中 key 是不同属性的名称,value 是一个包含两个值的数组,第一个值来自 obj1,第二个值来自 obj2 |
|
|
|
*/ |
|
|
|
public static List<FieldDiff> diff(Object obj1, Object obj2, String... ignoreFields) { |
|
|
|
return diff(obj1, obj2, false, ignoreFields); |
|
|
|
} |
|
|
|
} |