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
*/
@Component
public 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);
}
}
使用示例:
@Override
public <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;
}
}
}