【Java】字段值变动比较工具

更新数据库的数据时,需要把每次变动的内容记录下来。 通用工具—————只能比较基本类型和String。

实现

public class FieldCompareUtils {

    /**
     * 字段值变动比较工具
     * @param source
     * @param target
     * @return map形式 key字段名,value list.get(0) 改变前的值 list.get(1) 改变后的值 异常返回空
     */
    public static Map<String, List<Object>> fieldCompare(Object source, Object target) {

        if (source == null || target == null || source.getClass() != target.getClass()){
            return null;
        }
        try {
            HashMap<String, List<Object>> resultMap = new HashMap<>();

            // 获取 source 所有字段
            List<Field> sourceFields = getAllFields(source);

            // 字段map
            Map<String, Field> sourceFieldsMap = sourceFields.stream().collect(
                    Collectors.toMap(Field::getName, field -> field));

            // 获取target 所有字段
            List<Field> targetFields = getAllFields(target);

            // 循环比较
            for (Field targetField : targetFields) {
                String name = targetField.getName();
                Field sourceField = sourceFieldsMap.get(name);
                if (sourceField != null) {
                    Object sourceValue = sourceField.get(source);
                    Object targetValue = targetField.get(target);

                    // 字段值不同时记录下来
                    if (targetValue != null && !targetValue.equals(sourceValue)) {
                        List list = new ArrayList();
                        list.add(sourceValue);
                        list.add(targetValue);
                        resultMap.put(sourceField.getName(), list);
                    }

                }
            }
            return resultMap;
        }catch (IllegalAccessException e) {

        }

        return null;
    }

    /**
     * 获取包括父类在内的所有字段
     * @param source
     * @return
     */
    public static List<Field> getAllFields(Object source) {

        List<Field> fieldList = new ArrayList<>();
        Class clazz = source.getClass();
        while (clazz != Object.class) {
            Field[] declaredFields = clazz.getDeclaredFields();
            for (int i = 0; i < declaredFields.length; i++) {
                declaredFields[i].setAccessible(true);
                fieldList.add(declaredFields[i]);
            }
            clazz = clazz.getSuperclass();
        }
        return fieldList;
    }

    public static void main(String[] args) {

        Student source = new Student();
        Student target = new Student();

        source.name = "nihao";
        target.name = "test";
        target.age = 12;

        Map<String, List<Object>> stringListMap = fieldCompare(source, target);
        Gson gson = new Gson();
        System.out.println(gson.toJson(stringListMap));
    }
}
class Student{
    String name;
    Integer age;
}

运行结果

{"name":["nihao","test"],"age":[null,12]}

**
* 比较两个实体属性值,返回一个map以有差异的属性名为key,value为一个list分别存obj1,obj2此属性名的值
* @param obj1 进行属性比较的对象1
* @param obj2 进行属性比较的对象2
* @param ignoreArr 选择忽略比较的属性数组
* @return 属性差异比较结果map
**

@SuppressWarnings("rawtypes")
    public Map<String, List<Object>> compareFields(Object obj1, Object obj2, String[] ignoreArr) {
        try{
            Map<String, List<Object>> map = new HashMap<>();
            List<String> ignoreList = null;
            if(ignoreArr != null && ignoreArr.length > 0){
                // array转化为list
                ignoreList = Arrays.asList(ignoreArr);
            }
            // 只有两个对象都是同一类型的才有可比性
            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;
                    }
                    Method readMethod = pd.getReadMethod();
                    // get方法
                    // 在obj1上调用get方法等同于获得obj1的属性值
                    Object o1 = readMethod.invoke(obj1);
                    // 在obj2上调用get方法等同于获得obj2的属性值
                    Object o2 = readMethod.invoke(obj2);
                    DecimalFormat df = new DecimalFormat("#.0000");
                    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<Object> list = new ArrayList<>();
                        list.add("");
                        if(o2.equals("")){
                            //如果o2
                            list.add(null);
                        }else{
                            list.add(o2);
                            map.put(name, list);
                        }
                        continue;
                    }
                    if (!o1.equals(o2)) {
                        // 比较这两个值是否相等,不等就可以放入map了
                        List<Object> list = new ArrayList<>();
                        if(o1 != null && !o1.equals("")){
                            list.add(o1);
                        }else{
                            list.add("");
                        }
                        if(o2 != null && !o2.equals("")){
                            list.add(o2);
                        }else{
                            list.add("");
                        }
                        map.put(name, list);
                    }
                }
            }
            return map;
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }
    }

示例

比较意向合同表字段数据是否发生变更

public List<Contracthistory> intentContractChange(PropertyMakeIntentContractSaveParam param , Intentcontract intentcontract) {
        Intentcontract intentcontract1 = new Intentcontract();
        BeanUtils.copyProperties(param , intentcontract1);
        List<Contracthistory> contractHistoryVoList = new ArrayList<>();
        Intentcontract s1 = intentcontract1;
        Intentcontract s2 = intentcontract;
        // 比较s1和s2不同的属性值,其中“”里的字段忽略比较
        Map<String, List<Object>> compareResult = fieldCompareUtils.compareFields(s1, s2, new String[]{"intentContractId","createDate","createUser",
                "updateDate","updateUser", "contractCreateDate","version","remark","deleteFlag","defaultInt1","defaultInt2",
                "defaultInt3","defaultTime1","defaultTime2", "defaultNvarchar1","defaultNvarchar2","defaultNvarchar3","DefaultTime3"
        });
        Set<String> keySet = compareResult.keySet();
        List<Object> list;
        for(String key : keySet){
            list = compareResult.get(key);
            //查询字段中文名
            PropertyContractFieldCommentParam fieldCommentParam = new PropertyContractFieldCommentParam();
            fieldCommentParam.setTableName("IntentContract");
            fieldCommentParam.setField(key);
            PropertyFieldCommentVO fieldCommentVo = propertyFieldCommentMapperCustom.selectByTableAndFieldInfo(fieldCommentParam.getTableName(),fieldCommentParam.getField());
            Contracthistory contractHistory = new Contracthistory();
            contractHistory.setField(key);
            if(fieldCommentVo != null){
                contractHistory.setFieldName(fieldCommentVo.getFieldname());
            }
            //变更前字段值
            if(list.get(1).toString() != null && !("").equals(list.get(1).toString())){
                contractHistory.setBeforeValue(list.get(1).toString());
            }
            //变更后字段值1
            if(list.get(0).toString() != null && !("").equals(list.get(0).toString())){
                contractHistory.setAfterValue(list.get(0).toString());
            }
            contractHistoryVoList.add(contractHistory);
        }
        return contractHistoryVoList;
    }

查询表字段,字段名称sql

 SELECT
        col.name AS columnName,
        CONVERT(varchar(200), pro.VALUE) AS columnDescription,
        IIF (
        PATINDEX(
        '%[【,\[,(Z,(,(,\,,,]%',
        CONVERT (varchar(50), pro.[value])
        ) > 0,
        SUBSTRING (
        CONVERT (varchar(50), pro.[value]),
        1,
        PATINDEX(
        '%[【,\[,(Z,(,(,\,,,]%',
        CONVERT (varchar(50), pro.[value])
        ) - 1
        ),
        ISNULL(
        CONVERT (varchar(50), pro.[value]),
        ''
        )
        ) AS fieldname
        FROM
        sys.tables tbl
        INNER JOIN sys.columns col ON col.object_id = tbl.object_id
        LEFT JOIN sys.extended_properties pro  ON pro.major_id = col.object_id
        AND pro.minor_id = col.column_id
        WHERE 1=1
        <if test="tableName != null">
            AND tbl.name = #{tableName}
        </if>
        <if test="field != null">
            AND col.name = #{field}
        </if>

**#{tableName}:表名 #{field}:字段名(英文) **

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,如果要动态显示字段,可以使用反射机制。反射是Java中的一种机制,可以在运行时动态地获取类的字段、方法和构造函数等信息,并可以在运行时调用它们。 首先,我们需要使用Class类的forName()方法获取目标类的Class对象,例如: Class clazz = Class.forName("com.example.ClassName"); 然后,可以使用Class对象的getField()方法获取指定的字段,getField()方法需要传入字段的名称作为参数,例如: Field field = clazz.getField("fieldName"); 接下来,可以使用Field对象的get()方法获取字段,get()方法需要传入目标对象作为参数,例如: Object value = field.get(object); 需要注意的是,get()方法返回的是Object类型,如果字段的类型是基本数据类型,需要进行适当的类型转换。 最后,可以将字段动态地显示出来,可以使用System.out.println()方法将打印到控制台,例如: System.out.println("字段为:" + value); 通过上述步骤,我们可以在运行时动态地获取指定字段并进行显示。无论字段名称是固定的还是动态地生成,都可以通过反射机制来实现动态显示字段。这种方法在一些需要动态操作和显示字段的场景中非常有用,如配置文件读取、数据库操作等。需要注意的是,由于反射操作相对较耗时,所以在性能要求较高的场景中,应当谨慎使用反射。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值