1. package io.renren.utils;
  2. import cn.hutool.core.util.ObjectUtil;
  3. import org.springframework.stereotype.Component;
  4. import java.lang.reflect.Field;
  5. import java.util.HashMap;
  6. import java.util.Map;
  7. /**
  8. * 对象工具类
  9. * @author WHN
  10. * @Date: 2021/1/14 16:14
  11. */
  12. @Component
  13. public class ObjectCompareUtil {
  14. /**
  15. * 对象比较器,参数相同返回true,参数不同返回false
  16. * @author WHN
  17. * @date 2021/1/14 14:14
  18. * @param obj1:对象1
  19. * @param obj2:对象2
  20. * @return java.util.Map<java.lang.String,java.lang.Boolean>
  21. */
  22. public <T> Map<String, Boolean> compare(T obj1, T obj2) throws Exception {
  23. Map<String, Boolean> result = new HashMap<>();
  24. //获取所有属性
  25. Field[] fs = obj1.getClass().getDeclaredFields();
  26. for (Field f : fs) {
  27. //设置访问性,反射类的方法,设置为true就可以访问private修饰的东西,否则无法访问
  28. f.setAccessible(true);
  29. Object v1 = f.get(obj1);
  30. Object v2 = f.get(obj2);
  31. result.put(f.getName(), equals(v1, v2));
  32. }
  33. return result;
  34. }
  35. public static boolean equals(Object obj1, Object obj2) {
  36. if (ObjectUtil.isEmpty(obj1) && ObjectUtil.isEmpty(obj2)) {
  37. return true;
  38. }
  39. return ObjectUtil.equal(obj1, obj2);
  40. }
  41. }

使用示例:

  1. @Override
  2. public <T> T insertOrUpsertByMessageType(T messageEntity, List<String> msgParamByType) throws Exception {
  3. Class<?> aClass = messageEntity.getClass();
  4. //更新前的实体,查询该设备编号时间戳降序的第一条最新数据
  5. Query beforeQuery = new Query(
  6. Criteria.where(CommonsEnum.SBBH.getType()).is(ReflectUtil.getFieldValue(messageEntity, CommonsEnum.SBBH.getType()))
  7. ).with(Sort.by(
  8. Sort.Order.desc(CommonsEnum.GXSJC.getType()))
  9. );
  10. Object beforeUpdateMsg = mongoTemplate.findOne(beforeQuery, aClass);
  11. ReflectUtil.setFieldValue(messageEntity,CommonsEnum.GXSJ.getType(),DateUtil.date().toString());
  12. ReflectUtil.setFieldValue(messageEntity,CommonsEnum.GXSJC.getType(),DateUtil.date().getTime());
  13. //设备第一次上线,插入
  14. if (beforeUpdateMsg == null || ReflectUtil.getFieldValue(beforeUpdateMsg, CommonsEnum.SBBH.getType()) == null) {
  15. mongoTemplate.insert(messageEntity);
  16. //设备第一次上发数据,返回true
  17. return messageEntity;
  18. } else {
  19. //比较更新前的实体类 和 传入的实体类
  20. Map<String, Boolean> map = objectUtil.compare(beforeUpdateMsg,messageEntity);
  21. //比较之后,过滤掉为true的字段,找到只为false的数据 (更新了哪些字段)
  22. Map<String, Boolean> filterFalseMap = MapUtil.filter(map, (Filter<Map.Entry<String, Boolean>>) t -> !t.getValue());
  23. Map<String, Boolean> filterMap = MapUtil.filter(filterFalseMap, (Filter<Map.Entry<String, Boolean>>) t ->
  24. msgParamByType.contains(t.getKey()) || CommonsEnum.SBBH.getType().equals(t.getKey())
  25. );
  26. //数据要修改,找到传入参数中变化的字段,并在表中插入一条
  27. if (filterMap.size() > 0) {
  28. //发生变化的字段,形成嵌套文档
  29. HashMap<String, Object> loopMap = new HashMap<>();
  30. for (String key : filterMap.keySet()) {
  31. Object fieldValue = ReflectUtil.getFieldValue(messageEntity, key);
  32. loopMap.put(key, fieldValue);
  33. }
  34. ReflectUtil.setFieldValue(messageEntity,CommonsEnum.UPDATEDATA.getType(),loopMap);
  35. //新增一条数据
  36. mongoTemplate.insert(messageEntity);
  37. //最新报文与上一条报文相比,产生了变化,返回true
  38. return messageEntity;
  39. } else {
  40. //没有数据要修改,在原最新一条数据上修改时间字段
  41. Update update = new Update();
  42. update.set(CommonsEnum.GXSJ.getType(), DateUtil.date().toString());
  43. update.set(CommonsEnum.GXSJC.getType(), DateUtil.date().getTime());
  44. mongoTemplate.updateFirst(beforeQuery, update, aClass);
  45. //最新报文与上一条报文相比,无变化,返回false
  46. return null;
  47. }
  48. }
  49. }