
2. 提供一个工具类,可以比较一个对象里面,源对象,与修改后的对象,有哪些字段发生了改变, 第一步
-
- /**
- * @author qiankun.hu
- * @version 1.0.0
- * @createTime 2023年09月20日 17:00:00
- * @Description TODO
- */
- @Target({ElementType.FIELD})
- @Retention(RetentionPolicy.RUNTIME)
- public @interface ColumnInfo {
-
- /**
- * 字段code
- */
- String columnCode() default "";
-
- /**
- * 字段名称
- */
- String columnName() default "";
-
- /**
- * 字段类型
- */
- String columnType() default "";
- }
工具类代码
- import com.example.demo.config.ColumnInfo;
- import org.apache.commons.lang3.StringUtils;
- import org.springframework.beans.BeanUtils;
-
- import java.beans.Introspector;
- import java.beans.PropertyDescriptor;
- import java.lang.reflect.Field;
- import java.lang.reflect.Method;
- import java.sql.Timestamp;
- import java.util.*;
-
- /**
- * @author qiankun.hu
- * @version 1.0.0
- * @createTime 2023年09月20日 17:00:00
- * @Description TODO
- */
- public class MyBeanUtils extends BeanUtils {
-
- /**
- * 比较两个实体属性值,返回一个map以有差异的属性名为key,value为一个list分别存obj1,obj2此属性名的值
- *
- * @param obj1 源值
- * @param obj2 最新值
- * @param ignoreArr 选择忽略比较的属性数组
- * @return 属性差异比较结果map
- *
- * 后面考虑添加注解字段名和中文名称,已达到提示对应的中文信息
- */
- public static Map
> compareFields(Object obj1, Object obj2, String[] ignoreArr) { - try {
- Map
> map = new HashMap>(); - List
ignoreList = null; - if (ignoreArr != null && ignoreArr.length > 0) {
- // array转化为list
- ignoreList = Arrays.asList(ignoreArr);
- }
- if (obj1 == null) {
- Class clazz = obj2.getClass();
- // 获取object的属性描述
- PropertyDescriptor[] pds = Introspector.getBeanInfo(clazz,
- Object.class).getPropertyDescriptors();
- // 这里就是所有的属性了
- for (PropertyDescriptor pd : pds) {
- // 属性名
- String name = pd.getName();
- // 如果当前属性选择忽略比较,跳到下一次循环
- if (ignoreList != null && ignoreList.contains(name)) {
- continue;
- }
- // Field field = clazz.getDeclaredField(name);
- Field field;
- try {
- field = clazz.getDeclaredField(name);
- } catch (NoSuchFieldException e) {
- try {
- //此处用于解决继承导致的getDeclaredField不能直接获取父类属性的问题
- field = clazz.getSuperclass().getDeclaredField(name);
- } catch (NoSuchFieldException ee) {
- //此处用于解决继承导致的getDeclaredField不能直接获取父类属性的问题
- field = clazz.getSuperclass().getSuperclass().getDeclaredField(name);
- }
- }
- ColumnInfo columnInfo = field.getAnnotation(ColumnInfo.class);
- if (columnInfo != null) {
- String columName = columnInfo.columnName();
- String columnCode = columnInfo.columnCode();
- String columnType = columnInfo.columnType();
- name = name + "_" + columName + "_" + columnCode + "_" + columnType;
- } else {
- continue;
- }
- // get方法
- Method readMethod = pd.getReadMethod();
- Object o2 = readMethod.invoke(obj2);
- if (o2 != null) {
- List
- list.add(null);
- list.add(o2);
- map.put(name, list);
- }
- }
- } else {
- // 只有两个对象都是同一类型的才有可比性
- if (obj1.getClass() == obj2.getClass()) {
- Class clazz = obj1.getClass();
- // 获取object的属性描述
- PropertyDescriptor[] pds = Introspector.getBeanInfo(clazz,
- Object.class).getPropertyDescriptors();
- // 这里就是所有的属性了
- for (PropertyDescriptor pd : pds) {
- // 属性名
- String name = pd.getName();
- // 如果当前属性选择忽略比较,跳到下一次循环
- if (ignoreList != null && ignoreList.contains(name)) {
- continue;
- }
- //Field field = clazz.getDeclaredField(name);
- Field field;
- try {
- field = clazz.getDeclaredField(name);
- } catch (NoSuchFieldException e) {
- try {
- //此处用于解决继承导致的getDeclaredField不能直接获取父类属性的问题
- field = clazz.getSuperclass().getDeclaredField(name);
- } catch (NoSuchFieldException ee) {
- //此处用于解决继承导致的getDeclaredField不能直接获取父类属性的问题
- field = clazz.getSuperclass().getSuperclass().getDeclaredField(name);
- }
-
- }
- ColumnInfo columnInfo = field.getAnnotation(ColumnInfo.class);
- if (columnInfo != null) {
- String columName = columnInfo.columnName();
- String columnCode = columnInfo.columnCode();
- String columnType = columnInfo.columnType();
- name = name + "_" + columName + "_" + columnCode + "_" + columnType;
- } else {
- continue;
- }
- // get方法
- Method readMethod = pd.getReadMethod();
- // 在obj1上调用get方法等同于获得obj1的属性值
- Object o1 = readMethod.invoke(obj1);
- // 在obj2上调用get方法等同于获得obj2的属性值
- Object o2 = readMethod.invoke(obj2);
- if (o1 instanceof Timestamp) {
- o1 = new Date(((Timestamp) o1).getTime());
- }
- if (o2 instanceof Timestamp) {
- o2 = new Date(((Timestamp) o2).getTime());
- }
- if (o1 == null && o2 == null) {
- continue;
- } else if (o1 == null && o2 != null) {
- List
list = new ArrayList(); - list.add(o1);
- list.add(o2);
- if (o2 instanceof String && StringUtils.isBlank(String.valueOf(o2))) {
- o2 = null;
- }
- if (o2 != null) {
- map.put(name, list);
- }
- continue;
- }
- // 比较这两个值是否相等,不等就可以放入map了
- if (!o1.equals(o2)) {
- List
list = new ArrayList(); - list.add(o1);
- list.add(o2);
- if(o2!=null){
- o1 = o1 instanceof String && StringUtils.isBlank(String.valueOf(o1)) ? "" : o1;
- Object info = (o2 instanceof String && StringUtils.isBlank(String.valueOf(o2)) ? "" : o2);
- o2 = o2 == null ? "" : info;
- if(!o1.equals(o2)){
- map.put(name, list);
- }
- }
-
- }
- }
- }
- }
- return map;
- } catch (Exception e) {
- return null;
- }
- }
- }
3 进行测试
- import com.alibaba.fastjson.JSON;
- import com.example.demo.config.ColumnInfo;
- import com.example.demo.util.MyBeanUtils;
- import java.util.*;
-
-
- /**
- * @author qiankun.hu
- * @version 1.0.0
- * @createTime 2022年10月14日 13:35:00
- * @Description TODO
- */
- public class StudentDto {
-
- @ColumnInfo(columnCode = "name", columnName = "名称")
- private String name;
- @ColumnInfo(columnCode = "name", columnName = "名称")
- private String age;
- @ColumnInfo(columnCode = "studentNum", columnName = "学号")
- private Integer studentNum;
- @ColumnInfo(columnCode = "classNum", columnName = "班级号")
- private String classNum;
-
- public static void main(String[] args) {
- //老数据
- StudentDto s1 = new StudentDto();
- s1.setName("张三");
- s1.setAge("18");
- s1.setStudentNum(9001);
- s1.setClassNum("高一二班");
-
- //修改后的数据
- StudentDto s2 = new StudentDto();
- s2.setName("张三");
- s2.setAge("19");
- s2.setStudentNum(9002);
- s2.setClassNum("高一三班");
-
- //忽略对比的字段
- String[] arr = new String[1];
- arr[0] = "studentNum";
-
- //对比哪些字段发生改变,K 是发生改变的字段 value 是字段前后的变化
- Map
> stringListMap = MyBeanUtils.compareFields(s1, s2, null); -
- System.out.println( JSON.toJSONString(stringListMap) );
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getAge() {
- return age;
- }
-
- public void setAge(String age) {
- this.age = age;
- }
-
- public Integer getStudentNum() {
- return studentNum;
- }
-
- public void setStudentNum(Integer studentNum) {
- this.studentNum = studentNum;
- }
-
- public String getClassNum() {
- return classNum;
- }
-
- public void setClassNum(String classNum) {
- this.classNum = classNum;
- }
- }
输出结果如下:
{
"age_名称_name_": ["18", "19"],
"studentNum_学号_studentNum_": [9001, 9002],
"classNum_班级号_classNum_": ["高一二班", "高一三班"]
}
我们可以看到,对象修改后与修改后,相关字段产生的变化,如果有不需要对比的字段,传入相同的参数既可