1. 程式人生 > >java 實現更新記錄時 詳細記錄各欄位的具體更新細節日誌

java 實現更新記錄時 詳細記錄各欄位的具體更新細節日誌

1、需求 

假如資料庫中有一條記錄從

{"id":1,"name":"張三","age":21,"sex":true}

更新成

{"id":1,"name":"李四","age":24,"sex":false}

則生成詳細的日誌記錄

{

"id":1,"unityTag":"Person","unityOperate":"更新",

"unityMatter":"[姓名][年齡][性別]",

"unityContent":"[張三->李四][21->24][true->false]"

}

2、實現 

需要用到:反射 、註解

3、具體實現

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * @author printsky
 * @since 2018/8/29
 */
@Retention(RetentionPolicy.RUNTIME)
public @interface LogCompar {
    /**
     * 中文名稱
     *
     * @return String
     */
    String name();

    /**
     * Date 如何格式化,預設為空
     *
     * @return String
     */
    String dateFormat() default "";
}
/**
 * @author printsky
 * @since 2018/8/30
 */
public enum EnumTableName {
    Person("Person"),
    Province("Province"),
    Income("Income");

    EnumTableName(String tableName) {
        this.tableName = tableName;
    }

    private String tableName;

    public String getTableName() {
        return tableName;
    }
}
/**
 * @author printsky
 * @since 2018/08/28
 */
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public class UnityLog {
    /**
     * id
     */
    private Long id;

    /**
     * 資料庫表名
     */
    private String unityTag;

    /**
     * 資料庫表記錄id對應的操作日誌
     */
    private Long unityTagId;

    /**
     * 操作人
     */
    private String unityOperator;

    /**
     * 操作時間
     */
    private Date unityOperateTime;

    /**
     * 操作型別
     */
    private String unityOperate;

    /**
     * 操作事項
     */
    private String unityMatter;

    /**
     * 操作內容
     */
    private String unityContent;

    public UnityLog(Long id, String unityTag, Long unityTagId, String unityOperator, Date unityOperateTime, String unityOperate, String unityMatter, String unityContent) {
        this.id = id;
        this.unityTag = unityTag;
        this.unityTagId = unityTagId;
        this.unityOperator = unityOperator;
        this.unityOperateTime = unityOperateTime;
        this.unityOperate = unityOperate;
        this.unityMatter = unityMatter;
        this.unityContent = unityContent;
    }

    public UnityLog(UnityLogBuilder builder) {
        this.unityTag = builder.unityTag;
        this.unityTagId = builder.unityTagId;
        this.unityOperator = builder.unityOperator;
        this.unityOperate = builder.unityOperate;
        this.unityMatter = builder.unityMatter;
        this.unityContent = builder.unityContent;
    }

    public UnityLog() {
        super();
    }

    /**
     * id
     *
     * @return id id
     */
    public Long getId() {
        return id;
    }

    /**
     * id
     *
     * @param id id
     */
    public void setId(Long id) {
        this.id = id;
    }

    /**
     * 資料庫表名
     *
     * @return unity_tag 資料庫表名
     */
    public String getUnityTag() {
        return unityTag;
    }

    /**
     * 資料庫表名
     *
     * @param unityTag 資料庫表名
     */
    public void setUnityTag(String unityTag) {
        this.unityTag = unityTag == null ? null : unityTag.trim();
    }

    /**
     * 資料庫表記錄id對應的操作日誌
     *
     * @return unity_tag_id 資料庫表記錄id對應的操作日誌
     */
    public Long getUnityTagId() {
        return unityTagId;
    }

    /**
     * 資料庫表記錄id對應的操作日誌
     *
     * @param unityTagId 資料庫表記錄id對應的操作日誌
     */
    public void setUnityTagId(Long unityTagId) {
        this.unityTagId = unityTagId;
    }

    /**
     * 操作人
     *
     * @return unity_operator 操作人
     */
    public String getUnityOperator() {
        return unityOperator;
    }

    /**
     * 操作人
     *
     * @param unityOperator 操作人
     */
    public void setUnityOperator(String unityOperator) {
        this.unityOperator = unityOperator == null ? null : unityOperator.trim();
    }

    /**
     * 操作時間
     *
     * @return unity_operate_time 操作時間
     */
    public Date getUnityOperateTime() {
        return unityOperateTime;
    }

    /**
     * 操作時間
     *
     * @param unityOperateTime 操作時間
     */
    public void setUnityOperateTime(Date unityOperateTime) {
        this.unityOperateTime = unityOperateTime;
    }

    /**
     * 操作型別
     *
     * @return unity_operate 操作型別
     */
    public String getUnityOperate() {
        return unityOperate;
    }

    /**
     * 操作型別
     *
     * @param unityOperate 操作型別
     */
    public void setUnityOperate(String unityOperate) {
        this.unityOperate = unityOperate == null ? null : unityOperate.trim();
    }

    /**
     * 操作事項
     *
     * @return unity_matter 操作事項
     */
    public String getUnityMatter() {
        return unityMatter;
    }

    /**
     * 操作事項
     *
     * @param unityMatter 操作事項
     */
    public void setUnityMatter(String unityMatter) {
        this.unityMatter = unityMatter == null ? null : unityMatter.trim();
    }

    /**
     * 操作內容
     *
     * @return unity_content 操作內容
     */
    public String getUnityContent() {
        return unityContent;
    }

    /**
     * 操作內容
     *
     * @param unityContent 操作內容
     */
    public void setUnityContent(String unityContent) {
        this.unityContent = unityContent == null ? null : unityContent.trim();
    }

    public void setIdAndOperator(Long unityTagId, String unityOperator) {
        this.unityTagId = unityTagId;
        this.unityOperator = unityOperator;
    }


    public static UnityLogBuilder builder() {
        return new UnityLogBuilder();
    }

    public static class UnityLogBuilder {
        private String unityTag;
        private Long unityTagId;
        private String unityOperator;
        private String unityOperate;
        private String unityMatter;
        private String unityContent;

        public UnityLogBuilder unityTag(String unityTag) {
            this.unityTag = unityTag;
            return this;
        }

        public UnityLogBuilder unityTagId(Long unityTagId) {
            this.unityTagId = unityTagId;
            return this;
        }

        public UnityLogBuilder unityOperator(String unityOperator) {
            this.unityOperator = unityOperator;
            return this;
        }

        public UnityLogBuilder unityOperate(String unityOperate) {
            this.unityOperate = unityOperate;
            return this;
        }

        public UnityLogBuilder unityMatter(String unityMatter) {
            this.unityMatter = unityMatter;
            return this;
        }

        public UnityLogBuilder unityContent(String unityContent) {
            this.unityContent = unityContent;
            return this;
        }

        public UnityLog build() {
            return new UnityLog(this);
        }
    }
}
/**
 * @author printsky
 * @since 2018/8/30
 */
public class Person extends Base {
    @LogCompar(name = "id")
    private Long id;
    @LogCompar(name = "姓名")
    private String name;
    @LogCompar(name = "年齡")
    private Integer age;
    @LogCompar(name = "性別")
    private boolean sex;

    public Person() {
    }

    public Person(Long id, String name, Integer age, boolean sex) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public boolean isSex() {
        return sex;
    }

    public void setSex(boolean sex) {
        this.sex = sex;
    }

    @Override
    EnumTableName getTableName() {
        return EnumTableName.Person;
    }
}

這個類是主要的的邏輯實現部分 


import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author printsky
 * @since 2018/8/30
 */
public abstract class Base {
    public abstract Long getId();

    abstract EnumTableName getTableName();

    //region 生成資料修改日誌
    public final static String ADD = "新增";
    public final static String UPDATE = "更新";
    public final static String DELETE = "刪除";


    public <T extends Base> UnityLog createLog(String unityOperate, T oldObj) throws IllegalAccessException {
        //儲存操作日誌
        UnityLog unityLog = comparatorObject(unityOperate, oldObj);
        unityLog.setId(getId());
        return unityLog;
    }

    /**
     * 比較新老物件的差別
     *
     * @param unityOperate
     * @param oldObj
     * @return
     * @throws IllegalAccessException
     */
    private UnityLog comparatorObject(String unityOperate, Object oldObj) throws IllegalAccessException {
        StringBuilder matter = new StringBuilder();
        StringBuilder content = new StringBuilder();

        if (oldObj != null && UPDATE.equals(unityOperate)) {
            Map<String, Object> oldMap = changeValueToMap(oldObj);
            Map<String, Object> newMap = changeValueToMap(this);
            if (oldMap != null && !oldMap.isEmpty()) {
                for (Map.Entry<String, Object> entry : oldMap.entrySet()) {
                    Object oldValue = entry.getValue();
                    Object newValue = newMap.get(entry.getKey());
                    if (!oldValue.equals(newValue)) {
                        matter.append("[").append(entry.getKey()).append("]");
                        content.append("[").append(oldValue).append("->").append(newValue).append("]");
                    }
                }
            }
        } else {
            matter.append("-");
            content.append("-");
        }
        return UnityLog.builder()
                .unityOperate(unityOperate)
                .unityTag(getTableName().getTableName())
                .unityMatter(String.valueOf(matter))
                .unityContent(String.valueOf(content))
                .build();
    }

    /**
     * 將類物件轉換成Map
     *
     * @param entity 原物件
     * @return Map
     * @throws IllegalAccessException 型別轉換時報錯
     */
    private static Map<String, Object> changeValueToMap(Object entity) throws IllegalAccessException {
        Map<String, Object> resultMap = new HashMap<>();
        Field[] fields = entity.getClass().getDeclaredFields();
        for (Field field : fields) {
            String name = field.getName();
            if (PropertyUtils.isReadable(entity, name) && PropertyUtils.isWriteable(entity, name)) {
                if (field.isAnnotationPresent(LogCompar.class)) {
                    LogCompar anno = field.getAnnotation(LogCompar.class);
                    //獲取private物件欄位值
                    field.setAccessible(true);
                        resultMap.put(anno.name(), field.get(entity));
                }
            }
        }
        return resultMap;
    }
    //endregion

}
    public static void main(String[] args) {
        Gson gson=new Gson();
        Person user1=new Person(1L,"張三",21,true);
        System.out.println("user1 = " + gson.toJson(user1));
        Person user2=new Person(1L,"李四",24,false);
        System.out.println("user2 = " + gson.toJson(user2));

        try {
            UnityLog log = user2.createLog(Base.UPDATE, user1);
            System.out.println("log = " + gson.toJson(log));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }