先上工具类
import com.xunao.pojo.CompareResult;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
/**
* compare two objects
* 2020-3-4
* @author Joshua
*/
public class UpdateLogUtil {
public static List<CompareResult> updateLog(Object objOld, Object objNew) throws Exception {
List<CompareResult> compareResultList = new ArrayList<>();
Class oldClass = objOld.getClass();
if (!(oldClass.isInstance(objNew))) {
System.out.println("传入的两个java对象类型不一致!");
return null;
}
//获取字段 (私有字段也可以访问)
Field[] fields = oldClass.getDeclaredFields();
//remark记录变更
String remark = "";
for (Field field : fields) {
CompareResult compareResult = new CompareResult();
String name = field.getName();
String type = field.getType().getName();
//设置些属性是可以访问的
field.setAccessible(true);
//得到此属性的修改前值
Object valOld = field.get(objOld);
//得到此属性的修改后值
Object valNew = field.get(objNew);
//BigDecimal 类型的数据要去掉小数点后尾部的0不一致造成数据比对差异
if ("java.math.BigDecimal".equals(type) && valOld != null && valNew != null) {
BigDecimal valOldBig = new BigDecimal(String.valueOf(valOld));
BigDecimal valNewBig = new BigDecimal(String.valueOf(valNew));
//由于无法获取精度值,只能对所有带小数点的数据进行处理
if (String.valueOf(valOldBig).contains(".") || String.valueOf(valNewBig).contains(".")) {
DecimalFormat formatter1 = new DecimalFormat("0.000000");
valOld = formatter1.format(valOldBig);
valNew = formatter1.format(valNewBig);
}
}
if (!String.valueOf(valOld).equals(String.valueOf(valNew))) {
//保存处理数据
System.out.println("UpdateLogUtil.UpdateLog:" + name + "--" + valOld + "----" + valNew);
//获取属性上的指定类型的注解
XmlElement annotation = field.getAnnotation(XmlElement.class);
//有该类型的注解存在
if (annotation != null) {
//获取属性上的指定类型的注解的指定方法
//查询字段的不同 赋值
compareResult.setColumnName(annotation.name());
if (!StringUtil.isNullOrEmpty(valOld)) {
compareResult.setOldVal(String.valueOf(valOld));
} else {
compareResult.setOldVal("空");
}
if (!StringUtil.isNullOrEmpty(valNew)) {
compareResult.setNewVal(String.valueOf(valNew));
} else {
compareResult.setNewVal("空");
}
compareResultList.add(compareResult);
}
}
}
return compareResultList;
}
}
工具类用来比较统一实体对象前后数据的不同并做记录,在实体类中需要记录改变的字段加上"@XmlElement(name = “”)"注解.
为了防止前后的实体对象指向同一地址空间,保留旧数据时需要利用反射,代码如下:
/**
* copy object
*
* @param object source object
* @return new object
* @throws Exception nothing special
*/
public static Object copy(Object object) throws Exception {
// 获得对象的类型
Class<?> classType = object.getClass();
// 通过默认构造方法创建一个新的对象
Object objectCopy = classType.getConstructor(new Class[]{})
.newInstance();
// 获得对象的所有属性
Field[] fields = classType.getDeclaredFields();
for (Field field : fields) {
// 属性名称
String fieldName = field.getName();
// 得到属性名称的第一个字母并转成大写
String firstLetter = fieldName.substring(0, 1).toUpperCase();
// 获得和属性对应的getXXX()方法的名字:get+属性名称的第一个字母并转成大写+属性名去掉第一个字母,
// 如属性名称为name,则:get+N+ame
String getMethodName = "get" + firstLetter + fieldName.substring(1);
// 获得和属性对应的setXXX()方法的名字
String setMethodName = "set" + firstLetter + fieldName.substring(1);
// 获得和属性对应的getXXX()方法
Method getMethod = classType.getMethod(getMethodName
);
// 获得和属性对应的setXXX()方法,传入参数为参数的类型
Method setMethod = classType.getMethod(setMethodName,
field.getType());
// 调用原对象的getXXX()方法
Object value = getMethod.invoke(object);
System.out.println(fieldName + ":" + value);
// 调用拷贝对象的setXXX()方法
setMethod.invoke(objectCopy, value);
}
return objectCopy;
}
我用来接收方法返回的实体类CompareResult
import lombok.Data;
@Data
public class CompareResult {
public String columnName;
public String oldVal;
public String newVal;
}