java 数据更新前后对比工具类,主要用于记录数据变更前后的日志

1.使用反射机制获取Bean字段
2.使用自定义注解获取字段说明;
3.动态多种数据类型都可支持,数据类型可自行添加
上代码

调用方式:

List<String> compareLog = SerializableFieldCompare.compare(Test.class, newTest, oldTest);

工具类:


import org.apache.commons.lang3.StringUtils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SerializableFieldCompare {
    public static <T> List<String> compare (Class<T> type, T newObject, T  oldObject ) throws Exception {
        List<String> logList = new ArrayList<>();
        Class<?> newObj = newObject.getClass();
        Class<?> oldObj = oldObject.getClass();
        Field[] newFields = type.getDeclaredFields();
        for (int i = 0; i < newFields.length; i++) {
            FieldCompare newAnnotation = newFields[i].getAnnotation(FieldCompare.class);
            if(null != newAnnotation){
                PropertyDescriptor newPd = new PropertyDescriptor(newFields[i].getName(), newObj);
                Method getMethodNew = newPd.getReadMethod();
                Object oldVal = getMethodNew.invoke(oldObject);
                Object newVal = getMethodNew.invoke(newObject);
                boolean eq = false;
                if (oldVal instanceof String){
                    String s1 = String.valueOf(oldVal).trim();
                    String s2 = String.valueOf(newVal).trim();
                    eq = !s1.equals(s2);
                }else if(oldVal instanceof Integer){
                    int i1 = (Integer) oldVal;
                    int i2 = (Integer) newVal;
                    eq = i1 != i2;
                }else if(oldVal instanceof Double){
                    double d1 = (Double) oldVal;
                    double d2 = (Double) newVal;
                    eq = d1 != d2;
                }else if(oldVal instanceof BigDecimal){
                    BigDecimal b1 = (BigDecimal) oldVal;
                    BigDecimal b2 = (BigDecimal) newVal;
                    eq = b1.compareTo(b2) != 0;
                }else if(oldVal instanceof Long){
                    long l1 = (Long) oldVal;
                    long l2 = (Long) newVal;
                    eq = l1 != l2;
                }
                String s1 = oldVal == null ? "" : oldVal.toString().trim();
                String s2 = newVal == null ? "" : newVal.toString().trim();
                if (eq) {
                    Map<String, String> map = codeToNameMap(newAnnotation);
                    if (map.size() > 0) {
                        logList.add(newAnnotation.chineseName() + "由:[" + map.get(s1) + "]更改为了:[" + map.get(s2) + "]");
                    }else {
                        logList.add(newAnnotation.chineseName() + "由:[" + s1 + "]更改为了:[" + s2 + "]");
                    }
                }
            }
        }
        return logList;
    }

    private static Map<String,String> codeToNameMap(FieldCompare newAnnotation){
        Map<String,String> map = new HashMap<>();
        String properties = newAnnotation.properties();
        if(StringUtils.isNotBlank(properties)){
            String[] propertiesArr = properties.split(",");
            for (String propertie : propertiesArr) {
                String[] split = propertie.split(":");
                map.put(split[0],split[1]);
            }
        }
        return map;
    }
}

自定义注解类:

import java.lang.annotation.*;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface FieldCompare {

    //字段名称
    String chineseName();
    //类型映射
    String properties() default "";

}

测试Bean:
注解说明:
chineseName属性为字段名称
properties属性 是用来映射数字对应的类型名称

public class Test implements Serializable {
    private Integer id;

    private Integer serviceId;

    @FieldCompare(chineseName = "服务费收取方式", properties = "1:固定金额,2:百分比")
    private Integer serviceFeeCollectWay;

    @FieldCompare(chineseName = "线上")
    private BigDecimal servicePriceOnline;

    @FieldCompare(chineseName = "线下")
    private BigDecimal servicePriceOffline;

    private Integer type;

    private Date createTime;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getServiceId() {
        return serviceId;
    }

    public void setServiceId(Integer serviceId) {
        this.serviceId = serviceId;
    }

    public Integer getServiceFeeCollectWay() {
        return serviceFeeCollectWay;
    }

    public void setServiceFeeCollectWay(Integer serviceFeeCollectWay) {
        this.serviceFeeCollectWay = serviceFeeCollectWay;
    }

    public BigDecimal getServicePriceOnline() {
        return servicePriceOnline;
    }

    public void setServicePriceOnline(BigDecimal servicePriceOnline) {
        this.servicePriceOnline = servicePriceOnline;
    }

    public BigDecimal getServicePriceOffline() {
        return servicePriceOffline;
    }

    public void setServicePriceOffline(BigDecimal servicePriceOffline) {
        this.servicePriceOffline = servicePriceOffline;
    }

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
}
  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值