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

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

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

一、前言

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

二、條件限制

在寫這個(gè)通用方法時(shí),我們應(yīng)該考慮到以下幾點(diǎn):

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

(2)可以給字段進(jìn)行一個(gè)備注,因?yàn)槲覀兛吹降淖罱K內(nèi)容,應(yīng)該是一個(gè)中文名稱;

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

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

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

三、代碼

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) // 注解在運(yùn)行時(shí)保留,可通過反射獲取
public @interface CompareAnon {
 
    /**
     * 字段中文名稱
     */
    String name();
 
    /**
     * 前綴字段(進(jìn)行拼接,即:prefixField字段值 + name)
     */
    String prefixField() default "";
 
    /**
     * 比較字段(不用原字段進(jìn)行比較)
     */
    String compareField() default "";
 
    /**
     * 新增、刪除時(shí),是否用該值當(dāng)做“字段值”
     * 如:
     * 新增 -> 字段值
     * 字段值 -> 刪除
     */
    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 = "供應(yīng)商名稱", 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);
    }
 
    /**
     * 對比兩個(gè)對象修改值
     * @param oldObject 舊對象
     * @param newObject 新對象
     * @return 對比結(jié)果列表
     */
    public static List<ComparedResult> compareTwoObject(Object oldObject, Object newObject) {
        // 為null時(shí),不比較
        if (null == oldObject || null == newObject) {
            return Collections.emptyList();
        }
 
        // 不是同一個(gè)class
        if (oldObject.getClass() != newObject.getClass()) {
            throw new RuntimeException("不是同一個(gè)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(); // 格式
 
                // 前綴字段,存在(進(jìn)行拼接,即: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);
 
                // 對比兩個(gè)值是否一致
                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;
    }
 
    /**
     * 對比兩個(gè)對象修改值(檢查是否為null)
     * @param oldObject 舊對象
     * @param newObject 新對象
     * @return 對比結(jié)果列表
     */
    public static List<ComparedResult> compareTwoObjectCheckNull(Object oldObject, Object newObject) {
        // 都為null時(shí),不比較
        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時(shí),對比兩個(gè)對象修改值
        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(); // 是否用該值當(dāng)做“字段值”
 
                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(); // 是否用該值當(dāng)做“字段值”
 
                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("供應(yīng)商名稱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("供應(yīng)商名稱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("供應(yīng)商名稱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='供應(yīng)商名稱', oldValue=供應(yīng)商名稱1, newValue=供應(yīng)商名稱2, oldContent='供應(yīng)商名稱1', newContent='供應(yīng)商名稱2', pattern='', remark='供應(yīng)商名稱1 -> 供應(yīng)商名稱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實(shí)現(xiàn)對比兩個(gè)實(shí)體類字段變化的示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Java對比實(shí)體類字段變化的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java之操作Redis案例講解

    Java之操作Redis案例講解

    這篇文章主要介紹了Java之操作Redis案例講解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • springboot-controller的使用詳解

    springboot-controller的使用詳解

    本篇文章主要介紹了springboot-controller的使用詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • 通過Java帶你了解網(wǎng)絡(luò)IO模型

    通過Java帶你了解網(wǎng)絡(luò)IO模型

    這篇文章將通過Java帶大家了解網(wǎng)絡(luò)IO模型,包括BIO,NoBlockingIO,NIO(NewIO),AIO等做了詳細(xì)得介紹,感興趣的小伙伴可以參考閱讀本文
    2023-05-05
  • java -jar命令的具體使用

    java -jar命令的具體使用

    java -jar命令是一種方便快捷地在命令行中運(yùn)行Java可執(zhí)行jar文件的方法,本文主要介紹了java -jar命令的具體使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • java自定義類加載器如何實(shí)現(xiàn)類隔離

    java自定義類加載器如何實(shí)現(xiàn)類隔離

    這篇文章主要介紹了java自定義類加載器如何實(shí)現(xiàn)類隔離問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 超實(shí)用的Java快捷鍵(總結(jié))

    超實(shí)用的Java快捷鍵(總結(jié))

    下面小編就為大家?guī)硪黄瑢?shí)用的Java快捷鍵(總結(jié))。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • 分析講解SpringMVC注解配置如何實(shí)現(xiàn)

    分析講解SpringMVC注解配置如何實(shí)現(xiàn)

    這篇文章主要介紹了本文要介紹用注解方式代替web.xml與SpringMVC的配置文件,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • Spring注解之Service用法及示例詳解

    Spring注解之Service用法及示例詳解

    使用 @Service 注解可以將一個(gè)類聲明為業(yè)務(wù)邏輯組件,并將其對象存入 Spring 容器中,在控制器類中,通過注入該組件的實(shí)例,即可調(diào)用其中的方法,這篇文章主要介紹了Spring注解之Service用法及示例詳解,需要的朋友可以參考下
    2024-04-04
  • Java注解@Transactional事務(wù)類內(nèi)調(diào)用不生效問題及解決辦法

    Java注解@Transactional事務(wù)類內(nèi)調(diào)用不生效問題及解決辦法

    這篇文章主要介紹了Java注解@Transactional事務(wù)類內(nèi)調(diào)用不生效問題及解決辦法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • 細(xì)談java同步之JMM(Java Memory Model)

    細(xì)談java同步之JMM(Java Memory Model)

    Java內(nèi)存模型是在硬件內(nèi)存模型上的更高層的抽象,它屏蔽了各種硬件和操作系統(tǒng)訪問的差異性,保證了Java程序在各種平臺下對內(nèi)存的訪問都能達(dá)到一致的效果。下面我們來一起學(xué)習(xí)下JMM
    2019-05-05

最新評論