package io.renren.utils;import cn.hutool.core.util.ObjectUtil;import org.springframework.stereotype.Component;import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;/** * 对象工具类 * @author WHN * @Date: 2021/1/14 16:14 */@Componentpublic class ObjectCompareUtil { /** * 对象比较器,参数相同返回true,参数不同返回false * @author WHN * @date 2021/1/14 14:14 * @param obj1:对象1 * @param obj2:对象2 * @return java.util.Map<java.lang.String,java.lang.Boolean> */ public <T> Map<String, Boolean> compare(T obj1, T obj2) throws Exception { Map<String, Boolean> result = new HashMap<>(); //获取所有属性 Field[] fs = obj1.getClass().getDeclaredFields(); for (Field f : fs) { //设置访问性,反射类的方法,设置为true就可以访问private修饰的东西,否则无法访问 f.setAccessible(true); Object v1 = f.get(obj1); Object v2 = f.get(obj2); result.put(f.getName(), equals(v1, v2)); } return result; } public static boolean equals(Object obj1, Object obj2) { if (ObjectUtil.isEmpty(obj1) && ObjectUtil.isEmpty(obj2)) { return true; } return ObjectUtil.equal(obj1, obj2); }}
使用示例:
@Overridepublic <T> T insertOrUpsertByMessageType(T messageEntity, List<String> msgParamByType) throws Exception { Class<?> aClass = messageEntity.getClass(); //更新前的实体,查询该设备编号时间戳降序的第一条最新数据 Query beforeQuery = new Query( Criteria.where(CommonsEnum.SBBH.getType()).is(ReflectUtil.getFieldValue(messageEntity, CommonsEnum.SBBH.getType())) ).with(Sort.by( Sort.Order.desc(CommonsEnum.GXSJC.getType())) ); Object beforeUpdateMsg = mongoTemplate.findOne(beforeQuery, aClass); ReflectUtil.setFieldValue(messageEntity,CommonsEnum.GXSJ.getType(),DateUtil.date().toString()); ReflectUtil.setFieldValue(messageEntity,CommonsEnum.GXSJC.getType(),DateUtil.date().getTime()); //设备第一次上线,插入 if (beforeUpdateMsg == null || ReflectUtil.getFieldValue(beforeUpdateMsg, CommonsEnum.SBBH.getType()) == null) { mongoTemplate.insert(messageEntity); //设备第一次上发数据,返回true return messageEntity; } else { //比较更新前的实体类 和 传入的实体类 Map<String, Boolean> map = objectUtil.compare(beforeUpdateMsg,messageEntity); //比较之后,过滤掉为true的字段,找到只为false的数据 (更新了哪些字段) Map<String, Boolean> filterFalseMap = MapUtil.filter(map, (Filter<Map.Entry<String, Boolean>>) t -> !t.getValue()); Map<String, Boolean> filterMap = MapUtil.filter(filterFalseMap, (Filter<Map.Entry<String, Boolean>>) t -> msgParamByType.contains(t.getKey()) || CommonsEnum.SBBH.getType().equals(t.getKey()) ); //数据要修改,找到传入参数中变化的字段,并在表中插入一条 if (filterMap.size() > 0) { //发生变化的字段,形成嵌套文档 HashMap<String, Object> loopMap = new HashMap<>(); for (String key : filterMap.keySet()) { Object fieldValue = ReflectUtil.getFieldValue(messageEntity, key); loopMap.put(key, fieldValue); } ReflectUtil.setFieldValue(messageEntity,CommonsEnum.UPDATEDATA.getType(),loopMap); //新增一条数据 mongoTemplate.insert(messageEntity); //最新报文与上一条报文相比,产生了变化,返回true return messageEntity; } else { //没有数据要修改,在原最新一条数据上修改时间字段 Update update = new Update(); update.set(CommonsEnum.GXSJ.getType(), DateUtil.date().toString()); update.set(CommonsEnum.GXSJC.getType(), DateUtil.date().getTime()); mongoTemplate.updateFirst(beforeQuery, update, aClass); //最新报文与上一条报文相比,无变化,返回false return null; } }}