相关注解
- 忽略字段注解:该注解下的实体字段不参与文本对比
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnorField {
}
- Swagger-ApiModelProperty注解: 通过该注解获取字段中文说明
返回实体
@Data
@ApiModel("实体属性对比类")
public class CompareFiledInfo {
@ApiModelProperty("字段名称-对应字段名")
private String filedName;
@ApiModelProperty("字段说明-对应ApiModelProperty注解value值")
private String filedExplain;
@ApiModelProperty("原值")
private Object oldValue;
@ApiModelProperty("当前值")
private Object newValue;
}
@Data
@ApiModel("对象比较结果")
public class CompareObjInfo<T> {
@ApiModelProperty("操作类型 0-新增 1-修改 2-删除")
private int operateType;
@ApiModelProperty("旧对象")
private T oldObj;
@ApiModelProperty("新对象")
private T newObj;
}
文本登录工具类:
@Slf4j
public class PropertyUtils {
private PropertyUtils() {
}
public static <T> T transferObjectIgnoreCase(Object obj, Class<T> clz) {
T result = null;
try {
if (obj != null && !obj.equals("")) {
result = clz.newInstance();
Map<String, Field> destPropertyMap = new HashMap<>();
for (Field curField : clz.getDeclaredFields()) {
if (curField.isAnnotationPresent(IgnorField.class)) {
continue;
}
destPropertyMap.put(curField.getName().toLowerCase(), curField);
}
for (Field curField : obj.getClass().getDeclaredFields()) {
Field targetField = destPropertyMap.get(curField.getName().toLowerCase());
if (targetField != null) {
targetField.setAccessible(true);
curField.setAccessible(true);
targetField.set(result, curField.get(obj));
}
}
}
} catch (Exception e) {
log.error("忽略大小写转换bean类型失败", e);
return null;
}
return result;
}
public static <T> List<CompareObjInfo<T>> compareList(List<T> oldList, List<T> newList, String filed) {
boolean oldEmpty = CollUtil.isEmpty(oldList);
boolean newEmpty = CollUtil.isEmpty(newList);
if (oldEmpty || newEmpty) {
Asserts.fail(LocalLangUtil.get("property.utils.collectCompareEmptyErrorInfo"));
}
List<CompareObjInfo<T>> compareObjInfos = null;
if (oldEmpty && newEmpty) {
return compareObjInfos;
}
if (!oldEmpty && !newEmpty && (oldList.get(0).getClass() != newList.get(0).getClass())) {
Asserts.fail(LocalLangUtil.get("property.utils.collectCompareTypeErrorInfo"));
}
try {
Field field = oldList.get(0).getClass().getDeclaredField(filed);
field.setAccessible(true);
Map<Object, T> tempMap = new HashMap<>();
for (T value : oldList) {
tempMap.put(field.get(value), value);
}
compareObjInfos = new ArrayList<>();
CompareObjInfo<T> compareObjInfo;
for (T obj : newList) {
compareObjInfo = new CompareObjInfo<>();
Object newValueId = field.get(obj);
if (null == newValueId || !tempMap.containsKey(newValueId)) {
compareObjInfo.setOperateType(0);
compareObjInfo.setNewObj(obj);
compareObjInfos.add(compareObjInfo);
continue;
}
if (tempMap.containsKey(newValueId)) {
List<CompareFiledInfo> compareFiledInfos = compareObjFields(tempMap.get(newValueId), obj);
if (!compareFiledInfos.isEmpty()) {
compareObjInfo.setOperateType(1);
compareObjInfo.setOldObj(tempMap.get(newValueId));
compareObjInfo.setNewObj(obj);
compareObjInfos.add(compareObjInfo);
}
tempMap.remove(newValueId);
}
}
if (!tempMap.isEmpty()) {
for (T obj : tempMap.values()) {
compareObjInfo = new CompareObjInfo<>();
compareObjInfo.setOperateType(2);
compareObjInfo.setOldObj(obj);
compareObjInfo.setNewObj(null);
compareObjInfos.add(compareObjInfo);
}
}
} catch (Exception e) {
log.error("集合对比失败", e);
Asserts.fail(LocalLangUtil.get("property.utils.collectCompareFailedErrorInfo"));
}
return compareObjInfos;
}
public static <T> List<CompareFiledInfo> compareObjFields(T oldObj, T newObj) {
List<CompareFiledInfo> changeFileds = new ArrayList<>();
try {
Class<?> clazz = oldObj.getClass();
PropertyDescriptor[] pds = Introspector.getBeanInfo(clazz, Object.class).getPropertyDescriptors();
CompareFiledInfo compareFiledInfo = null;
for (PropertyDescriptor pd : pds) {
compareFiledInfo = new CompareFiledInfo();
String name = pd.getName();
Field filed = oldObj.getClass().getDeclaredField(name);
if (filed.isAnnotationPresent(IgnorField.class)) {
continue;
}
compareFiledInfo.setFiledName(name);
if (filed.isAnnotationPresent(ApiModelProperty.class)) {
compareFiledInfo.setFiledExplain(filed.getAnnotation(ApiModelProperty.class).value());
}
Method readMethod = pd.getReadMethod();
Object oldValue = readMethod.invoke(oldObj);
Object newValue = readMethod.invoke(newObj);
boolean whetherChange = (ObjectUtil.isEmpty(oldValue) && ObjectUtil.isNotEmpty(newValue)) || (ObjectUtil.isNotEmpty(oldValue) && ObjectUtil.isEmpty(newValue));
if (ObjectUtil.isNotEmpty(oldValue) && ObjectUtil.isNotEmpty(newValue)) {
if (pd.getPropertyType() != BigDecimal.class) {
whetherChange = !oldValue.equals(newValue);
} else {
BigDecimal oldDecimal = (BigDecimal) oldValue;
BigDecimal newDecimal = (BigDecimal) newValue;
whetherChange = oldDecimal.compareTo(newDecimal) != 0;
}
}
if (whetherChange) {
compareFiledInfo.setOldValue(oldValue);
compareFiledInfo.setNewValue(newValue);
changeFileds.add(compareFiledInfo);
}
}
} catch (Exception e) {
log.error("字段对比失败", e);
Asserts.fail(LocalLangUtil.get("property.utils.filedtCompareFailedErrorInfo"));
}
return changeFileds;
}
}
使用说明
public class CapitalMargin {
@ApiModelProperty(value = "主键")
@IgnorField
private Long id;
@ApiModelProperty(value = "所属时间")
@IgnorField
private LocalDateTime belongDate;
@ApiModelProperty(value = "所属修改时间")
@IgnorField
private LocalDateTime belongChangeDate;
@ApiModelProperty(value = "产品类型数据字典id")
private Long productTypeId;
}
List<CompareObjInfo<CapitalMargin>> compareObjInfos = PropertyUtils.compareList(list, allInfos, "no");
if (!CollUtil.isEmpty(compareObjInfos)) {
insertList = new ArrayList<>();
updateList = new ArrayList<>();
deleteList = new ArrayList<>();
for (CompareObjInfo<CapitalMargin> compareObjInfo : compareObjInfos) {
int operateType = compareObjInfo.getOperateType();
switch (operateType) {
case 0:
insertList.add(compareObjInfo.getNewObj());
break;
case 1:
Long id = compareObjInfo.getOldObj().getId();
updateList.add(id);
CapitalMargin newObj = compareObjInfo.getNewObj();
newObj.setBelongChangeId(id);
newObj.setStatusChangeReson("0");
insertList.add(newObj);
break;
case 2:
deleteList.add(compareObjInfo.getOldObj().getId());
break;
default:
break;
}
}
}