欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java實現(xiàn)對比兩個實體類字段變化的示例詳解

 更新時間:2024年03月20日 14:31:53   作者:木辰風  
我們在工作中,可能會在日志中記錄數(shù)據(jù)的變化情況或者在公共處理的數(shù)據(jù)增加一個日志頁面,我們可以根據(jù)CompareUtils工具類比較數(shù)據(jù)前后發(fā)生了怎樣的變化,下面我們就來看看具體實現(xiàn)吧

一、前言

我們在工作中,可能會在日志中記錄數(shù)據(jù)的變化情況或者在公共處理的數(shù)據(jù)增加一個日志頁面,記錄每次修改的變化。我們可以根據(jù)CompareUtils工具類比較數(shù)據(jù)前后發(fā)生了怎樣的變化,這樣我們就可以知道數(shù)據(jù)做了哪些改變。

二、條件限制

在寫這個通用方法時,我們應該考慮到以下幾點:

(1)可以接收任何對象的比較,但比較的對象應該是同個對象;

(2)可以給字段進行一個備注,因為我們看到的最終內(nèi)容,應該是一個中文名稱;

(3)一個對象中,可以注解來獲取某些字段進行比較,沒有注解的不需要進行比較;

(4)一個對象中,可以使用其他字段進行比較,輸出某些字段,如對字段userName進行注解,使用userId(用戶id)進行比較,輸出userName(用戶名稱);

(5)一個對象中,可以對字段進行格式化輸出,如金額、日期時間等。

三、代碼

CompareAnon(比較接口)(自定義注解)

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
/**
 * 對比注解
 */
@Target(value = {ElementType.TYPE, ElementType.FIELD}) // 允許被修飾的注解作用在類、接口和枚舉上 // 允許作用在屬性字段上
@Retention(RetentionPolicy.RUNTIME) // 注解在運行時保留,可通過反射獲取
public @interface CompareAnon {
 
    /**
     * 字段中文名稱
     */
    String name();
 
    /**
     * 前綴字段(進行拼接,即:prefixField字段值 + name)
     */
    String prefixField() default "";
 
    /**
     * 比較字段(不用原字段進行比較)
     */
    String compareField() default "";
 
    /**
     * 新增、刪除時,是否用該值當做“字段值”
     * 如:
     * 新增 -> 字段值
     * 字段值 -> 刪除
     */
    boolean asContent() default false;
 
    /**
     * 格式
     */
    String pattern() default "";
 
}

ComparedResult(對比結(jié)果)

import java.io.Serializable;
 
/**
 * 對比結(jié)果
 */
public class ComparedResult implements Serializable {
 
    /**
     * 對比字段
     */
    private String field;
 
    /**
     * 對比字段名稱(說明)
     */
    private String fieldName;
 
    /**
     * 原來的值
     */
    private Object oldValue;
 
    /**
     * 修改后的值
     */
    private Object newValue;
 
    /**
     * 原來的值(字符串)
     */
    private String oldContent;
 
    /**
     * 修改后的值(字符串)
     */
    private String newContent;
 
    /**
     * 格式
     */
    private String pattern;
 
    /**
     * 備注
     */
    private String remark;
 
    public String getField() {
        return field;
    }
 
    public void setField(String field) {
        this.field = field;
    }
 
    public String getFieldName() {
        return fieldName;
    }
 
    public void setFieldName(String fieldName) {
        this.fieldName = fieldName;
    }
 
    public Object getOldValue() {
        return oldValue;
    }
 
    public void setOldValue(Object oldValue) {
        this.oldValue = oldValue;
    }
 
    public Object getNewValue() {
        return newValue;
    }
 
    public void setNewValue(Object newValue) {
        this.newValue = newValue;
    }
 
    public String getOldContent() {
        return oldContent;
    }
 
    public void setOldContent(String oldContent) {
        this.oldContent = oldContent;
    }
 
    public String getNewContent() {
        return newContent;
    }
 
    public void setNewContent(String newContent) {
        this.newContent = newContent;
    }
 
    public String getPattern() {
        return pattern;
    }
 
    public void setPattern(String pattern) {
        this.pattern = pattern;
    }
 
    public String getRemark() {
        return remark;
    }
 
    public void setRemark(String remark) {
        this.remark = remark;
    }
 
    @Override
    public String toString() {
        return "ComparedResult{" +
                "field='" + field + '\'' +
                ", fieldName='" + fieldName + '\'' +
                ", oldValue=" + oldValue +
                ", newValue=" + newValue +
                ", oldContent='" + oldContent + '\'' +
                ", newContent='" + newContent + '\'' +
                ", pattern='" + pattern + '\'' +
                ", remark='" + remark + '\'' +
                '}';
    }
}

訂單DTO(測試類)

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
 
/**
 * 訂單DTO
 */
@CompareAnon(name = "訂單")
public class OrderDTO implements Serializable {
 
    @CompareAnon(name = "訂單id")
    private String id;
 
    @CompareAnon(name = "訂單編號", asContent = true)
    private String orderCode;
 
    private String supplyId;
 
    @CompareAnon(name = "供應商名稱", compareField = "supplyId")
    private String supplyName;
 
    @CompareAnon(name = "訂單金額(元)", pattern = "#,##0.0000")
    private BigDecimal orderAmount;
 
    @CompareAnon(name = "下單日期", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date orderDate;
 
    public String getId() {
        return id;
    }
 
    public void setId(String id) {
        this.id = id;
    }
 
    public String getOrderCode() {
        return orderCode;
    }
 
    public void setOrderCode(String orderCode) {
        this.orderCode = orderCode;
    }
 
    public String getSupplyId() {
        return supplyId;
    }
 
    public void setSupplyId(String supplyId) {
        this.supplyId = supplyId;
    }
 
    public String getSupplyName() {
        return supplyName;
    }
 
    public void setSupplyName(String supplyName) {
        this.supplyName = supplyName;
    }
 
    public BigDecimal getOrderAmount() {
        return orderAmount;
    }
 
    public void setOrderAmount(BigDecimal orderAmount) {
        this.orderAmount = orderAmount;
    }
 
    public Date getOrderDate() {
        return orderDate;
    }
 
    public void setOrderDate(Date orderDate) {
        this.orderDate = orderDate;
    }
 
}

CompareUtils(比較工具類)

import org.apache.commons.lang.StringUtils;
 
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
 
/**
 * 比較工具類
 */
public class CompareUtils {
 
    /**
     * 比較不同值,是否相等
     *
     * @param o1  值1
     * @param o2  值2
     * @return 比較結(jié)果,true相等,false不相等
     */
    public static boolean compareValues(Object o1, Object o2) {
        if (o1 == null && o2 == null) {
            return true;
        }
        if (o1 != null && o2 == null) {
            return false;
        }
        if (o1 == null && o2 != null) {
            return false;
        }
 
        // BigDecimal比較用compareTo
        if (o1 instanceof BigDecimal && o2 instanceof BigDecimal) {
            BigDecimal decimal1 = new BigDecimal(String.valueOf(o1));
            BigDecimal decimal2 = new BigDecimal(String.valueOf(o2));
            // 0相等
            return decimal1.compareTo(decimal2) == 0;
        }
 
        if (o1 instanceof Timestamp) {
            o1 = new Date(((Timestamp) o1).getTime());
        }
        if (o2 instanceof Timestamp) {
            o2 = new Date(((Timestamp) o2).getTime());
        }
 
        return Objects.equals(o1, o2);
    }
 
    /**
     * 對比兩個對象修改值
     * @param oldObject 舊對象
     * @param newObject 新對象
     * @return 對比結(jié)果列表
     */
    public static List<ComparedResult> compareTwoObject(Object oldObject, Object newObject) {
        // 為null時,不比較
        if (null == oldObject || null == newObject) {
            return Collections.emptyList();
        }
 
        // 不是同一個class
        if (oldObject.getClass() != newObject.getClass()) {
            throw new RuntimeException("不是同一個class!");
        }
 
        List<ComparedResult> comparedResultList = new ArrayList<>();
        Class<?> clazz = oldObject.getClass();
 
        // 獲取所有字段
        Field[] Fields = clazz.getDeclaredFields();
        for (Field field : Fields) {
            try {
 
                // 獲取注解
                CompareAnon compareAnon = field.getAnnotation(CompareAnon.class);
                // 沒有注解,說明不對比字段,跳過
                if (null == compareAnon) {
                    continue;
                }
 
                String fieldKey = field.getName(); // 字段名
                String filedName = compareAnon.name(); // 字段中文名稱
                String pattern = compareAnon.pattern(); // 格式
 
                // 前綴字段,存在(進行拼接,即:prefixField字段值 + name)
                String prefixField = compareAnon.prefixField();
                if (StringUtils.isNotBlank(prefixField)) {
                    filedName = getFieldValue(prefixField, oldObject) + filedName;
                }
 
                // 比較字段名
                String compareField = field.getName();
                if (StringUtils.isNotBlank(compareAnon.compareField())) {
                    compareField = compareAnon.compareField();
                }
 
                // 獲取比較的屬性值
                // 在oldObject上調(diào)用get方法等同于獲得oldObject的屬性值
                Object oldCompareValue = getFieldValue(compareField, oldObject);
                // 在newObject上調(diào)用get方法等同于獲得newObject的屬性值
                Object newCompareValue = getFieldValue(compareField, newObject);
 
                // 在oldObject上調(diào)用get方法等同于獲得oldObject的屬性值
                Object oldValue = getFieldValue(fieldKey, oldObject);
                // 在newObject上調(diào)用get方法等同于獲得newObject的屬性值
                Object newValue = getFieldValue(fieldKey, newObject);
 
                // 原來的值(字符串)
                String oldContent = CastUtils.getFormatValue(oldValue, pattern);
                // 修改后的值(字符串)
                String newContent = CastUtils.getFormatValue(newValue, pattern);
 
                // 對比兩個值是否一致
                if (!compareValues(oldCompareValue, newCompareValue)) {
                    // 不一致
                    ComparedResult result = new ComparedResult();
                    result.setField(fieldKey);
                    result.setFieldName(filedName);
                    result.setOldValue(oldValue);
                    result.setNewValue(newValue);
                    result.setOldContent(oldContent);
                    result.setNewContent(newContent);
                    result.setPattern(pattern);
                    result.setRemark(oldContent + " -> " + newContent);
                    comparedResultList.add(result);
                }
 
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
 
        return comparedResultList;
    }
 
    /**
     * 對比兩個對象修改值(檢查是否為null)
     * @param oldObject 舊對象
     * @param newObject 新對象
     * @return 對比結(jié)果列表
     */
    public static List<ComparedResult> compareTwoObjectCheckNull(Object oldObject, Object newObject) {
        // 都為null時,不比較
        if (null == oldObject && null == newObject) {
            return Collections.emptyList();
        }
 
        // 新增
        if (null == oldObject && null != newObject) {
            // 返回新增對比結(jié)果
            return addComparedResult(newObject);
        }
 
        // 刪除
        if (null != oldObject && null == newObject) {
            // 返回刪除對比結(jié)果
            return deleteComparedResult(oldObject);
        }
 
        // 都不為null時,對比兩個對象修改值
        return compareTwoObject(oldObject, newObject);
    }
 
    /**
     * 新增對比結(jié)果
     * @param obj 對象
     * @return 對比結(jié)果
     */
    public static List<ComparedResult> addComparedResult(Object obj) {
        List<ComparedResult> comparedResultList = new ArrayList<>();
        Class<?> clazz = obj.getClass();
 
        String filedName = ""; // 字段中文名稱
        String content = ""; // 內(nèi)容
 
        // 獲取類注解
        CompareAnon anon = clazz.getAnnotation(CompareAnon.class);
        if (null != anon) {
            filedName = anon.name();
        }
 
        // 獲取所有字段
        Field[] Fields = clazz.getDeclaredFields();
        for (Field field : Fields) {
            try {
 
                // 獲取注解
                CompareAnon compareAnon = field.getAnnotation(CompareAnon.class);
                // 沒有注解,說明不對比字段,跳過
                if (null == compareAnon) {
                    continue;
                }
 
                String fieldKey = field.getName(); // 字段名
                boolean asContent = compareAnon.asContent(); // 是否用該值當做“字段值”
 
                if (asContent) {
                    Object value = getFieldValue(fieldKey, obj); // 字段值
                    content = CastUtils.getFormatValue(value, null);
                }
 
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
 
        // 新增結(jié)果
        ComparedResult result = new ComparedResult();
        result.setFieldName(filedName);
        result.setOldContent("新增");
        result.setNewContent(content);
        result.setRemark("新增");
        comparedResultList.add(result);
 
        return comparedResultList;
    }
 
    /**
     * 刪除對比結(jié)果
     * @param obj 對象
     * @return 對比結(jié)果
     */
    public static List<ComparedResult> deleteComparedResult(Object obj) {
        List<ComparedResult> comparedResultList = new ArrayList<>();
        Class<?> clazz = obj.getClass();
 
        String filedName = ""; // 字段中文名稱
        String content = ""; // 內(nèi)容
 
        // 獲取class注解
        CompareAnon anon = clazz.getAnnotation(CompareAnon.class);
        if (null != anon) {
            filedName = anon.name();
        }
 
        // 獲取所有字段
        Field[] Fields = clazz.getDeclaredFields();
        for (Field field : Fields) {
            try {
 
                // 獲取注解
                CompareAnon compareAnon = field.getAnnotation(CompareAnon.class);
                // 沒有注解,說明不對比字段,跳過
                if (null == compareAnon) {
                    continue;
                }
 
                String fieldKey = field.getName(); // 字段名
                boolean asContent = compareAnon.asContent(); // 是否用該值當做“字段值”
 
                if (asContent) {
                    Object value = getFieldValue(fieldKey, obj); // 字段值
                    content = CastUtils.getFormatValue(value, null);
                }
 
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
 
        // 刪除結(jié)果
        ComparedResult result = new ComparedResult();
        result.setFieldName(filedName);
        result.setOldContent(content);
        result.setNewContent("刪除");
        result.setRemark("刪除");
        comparedResultList.add(result);
 
        return comparedResultList;
    }
 
    /**
     * 獲取字段值
     * @param fieldKey 字段名稱
     * @param obj 對象
     * @return 字段值
     * @throws Exception 異常
     */
    public static Object getFieldValue(String fieldKey, Object obj) throws Exception {
        PropertyDescriptor pd = new PropertyDescriptor(fieldKey, obj.getClass());
        Method getMethod = pd.getReadMethod();
 
        // 在obj上調(diào)用get方法等同于獲得obj的屬性值
        return getMethod.invoke(obj);
    }
 
    public static void main(String[] args) {
 
        System.out.println(compareValues(null, null));
        System.out.println(compareValues(2, null));
        System.out.println(compareValues(null, 2));
        System.out.println(compareValues(2, 2));
        System.out.println(compareValues("2", "2"));
        System.out.println(compareValues(2, "2"));
 
        System.out.println("------------------------BigDecimal---------------------------");
 
        System.out.println(compareValues(new BigDecimal("2"), "2"));
        System.out.println(compareValues(new BigDecimal("2"), new BigDecimal("2.0000")));
        System.out.println(compareValues(new BigDecimal("2.00"), new BigDecimal("2.0000")));
        System.out.println(compareValues(new BigDecimal("2.0000"), new BigDecimal("2.0000")));
        System.out.println(compareValues(new BigDecimal("2.0000"), new BigDecimal("3.0000")));
 
        System.out.println("------------------------comparedResultList---------------------------");
 
        OrderDTO oldDTO = new OrderDTO();
        oldDTO.setId("1");
        oldDTO.setOrderCode("訂單1");
        oldDTO.setSupplyId("1");
        oldDTO.setSupplyName("供應商名稱1");
        oldDTO.setOrderAmount(new BigDecimal("111111"));
        oldDTO.setOrderDate(new Date());
 
        OrderDTO newDTO = new OrderDTO();
        newDTO.setId("2");
        newDTO.setOrderCode("訂單2");
        newDTO.setSupplyId("2");
        newDTO.setSupplyName("供應商名稱2");
        newDTO.setOrderAmount(new BigDecimal("222222"));
        newDTO.setOrderDate(DateUtil.getBelowDay(new Date()));
 
        List<ComparedResult> comparedResultList = compareTwoObject(oldDTO, newDTO);
        for (ComparedResult comparedResult : comparedResultList) {
            System.out.println(comparedResult.toString());
        }
 
        System.out.println("------------------------comparedResultList2---------------------------");
 
        OrderDTO orderDTO = new OrderDTO();
        orderDTO.setId("3");
        orderDTO.setOrderCode("訂單3");
        orderDTO.setSupplyId("3");
        orderDTO.setSupplyName("供應商名稱3");
        orderDTO.setOrderAmount(new BigDecimal("333333"));
        orderDTO.setOrderDate(DateUtil.getBelowDay(new Date()));
        List<ComparedResult> comparedResultList2 = compareTwoObjectCheckNull(null, orderDTO);
        for (ComparedResult comparedResult : comparedResultList2) {
            System.out.println(comparedResult.toString());
        }
 
        System.out.println("------------------------comparedResultList3---------------------------");
 
        List<ComparedResult> comparedResultList3 = compareTwoObjectCheckNull(orderDTO, null);
        for (ComparedResult comparedResult : comparedResultList3) {
            System.out.println(comparedResult.toString());
        }
 
    }
 
}

四、main方法,輸出結(jié)果

true
false
false
true
true
false
------------------------BigDecimal---------------------------
false
true
true
true
false
------------------------comparedResultList---------------------------
ComparedResult{field='id', fieldName='訂單id', oldValue=1, newValue=2, oldContent='1', newContent='2', pattern='', remark='1 -> 2'}
ComparedResult{field='orderCode', fieldName='訂單編號', oldValue=訂單1, newValue=訂單2, oldContent='訂單1', newContent='訂單2', pattern='', remark='訂單1 -> 訂單2'}
ComparedResult{field='supplyName', fieldName='供應商名稱', oldValue=供應商名稱1, newValue=供應商名稱2, oldContent='供應商名稱1', newContent='供應商名稱2', pattern='', remark='供應商名稱1 -> 供應商名稱2'}
ComparedResult{field='orderAmount', fieldName='訂單金額(元)', oldValue=111111, newValue=222222, oldContent='111,111.0000', newContent='222,222.0000', pattern='#,##0.0000', remark='111,111.0000 -> 222,222.0000'}
ComparedResult{field='orderDate', fieldName='下單日期', oldValue=Wed Mar 20 11:51:22 CST 2024, newValue=Thu Mar 21 11:51:22 CST 2024, oldContent='2024-03-20 11:51:22', newContent='2024-03-21 11:51:22', pattern='yyyy-MM-dd HH:mm:ss', remark='2024-03-20 11:51:22 -> 2024-03-21 11:51:22'}
------------------------comparedResultList2---------------------------
ComparedResult{field='null', fieldName='訂單', oldValue=null, newValue=null, oldContent='新增', newContent='訂單3', pattern='null', remark='新增'}
------------------------comparedResultList3---------------------------
ComparedResult{field='null', fieldName='訂單', oldValue=null, newValue=null, oldContent='訂單3', newContent='刪除', pattern='null', remark='刪除'}

以上就是Java實現(xiàn)對比兩個實體類字段變化的示例詳解的詳細內(nèi)容,更多關(guān)于Java對比實體類字段變化的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 如何用Java的swing編寫簡單計算器

    如何用Java的swing編寫簡單計算器

    這篇文章主要給大家介紹了關(guān)于如何用Java的swing編寫簡單計算器的相關(guān)資料,通過本文可以設(shè)計一個圖形界面的簡易計算器,完成簡單的算術(shù)運算符,可以完成加法、減法、乘法、除法和取余運算,需要的朋友可以參考下
    2023-12-12
  • SpringSecurity實現(xiàn)自定義登錄方式

    SpringSecurity實現(xiàn)自定義登錄方式

    本文介紹自定義登錄流程,包括自定義AuthenticationToken、AuthenticationFilter、AuthenticationProvider以及SecurityConfig配置類,詳細解析了認證流程的實現(xiàn),為開發(fā)人員提供了具體的實施指導和參考
    2024-09-09
  • Java中\(zhòng)n和\r區(qū)別

    Java中\(zhòng)n和\r區(qū)別

    本文主要介紹了Java中\(zhòng)n和\r區(qū)別。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • Spring?Boot中使用Spring?MVC的示例解析

    Spring?Boot中使用Spring?MVC的示例解析

    MVC?是一種常見的軟件設(shè)計模式,用于分離應用程序的不同部分以實現(xiàn)松散耦合和高內(nèi)聚性,這篇文章主要介紹了如何在Spring?Boot中使用Spring?MVC,需要的朋友可以參考下
    2023-04-04
  • IDEA新建bootstrap.yml文件不顯示葉子圖標的問題

    IDEA新建bootstrap.yml文件不顯示葉子圖標的問題

    這篇文章主要介紹了IDEA新建bootstrap.yml文件不顯示葉子圖標的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 用java WebSocket做一個聊天室

    用java WebSocket做一個聊天室

    這篇文章主要為大家詳細介紹了用java WebSocket做一個聊天室,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • java日期操作工具類(獲取指定日期、日期轉(zhuǎn)換、相隔天數(shù))

    java日期操作工具類(獲取指定日期、日期轉(zhuǎn)換、相隔天數(shù))

    這篇文章主要為大家詳細介紹了java日期操作工具類,包括獲取指定日期、日期轉(zhuǎn)換、相隔天數(shù)等操作,感興趣的小伙伴們可以參考一下
    2016-06-06
  • Java正則替換手機號代碼實例

    Java正則替換手機號代碼實例

    本文的主要內(nèi)容是Java語言中正則表達式替換手機號的第4到第7位,實現(xiàn)方法十分簡單,同時涉及了一些正則表達式的相關(guān)用法,需要的朋友可以參考下。
    2017-09-09
  • MyBatis-Generator的配置說明和使用

    MyBatis-Generator的配置說明和使用

    本文主要介紹了MyBatis-Generator的配置說明和使用的相關(guān)知識。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • mybatis+lombok出現(xiàn)java.lang.IndexOutOfBoundsException錯誤及解決

    mybatis+lombok出現(xiàn)java.lang.IndexOutOfBoundsException錯誤及解決

    在使用MyBatis和Lombok時,如果遇到j(luò)ava.lang.IndexOutOfBoundsException問題,是因為MyBatis在嘗試將查詢結(jié)果封裝成Java對象時,找不到構(gòu)造函數(shù)中對應的字段,這通常是由于Lombok的@Builder注解生成了全參構(gòu)造函數(shù)
    2025-02-02

最新評論