【问题标题】:How to find all 'missing' and 'extra' fields in dto by their entity using Reflection?如何使用反射通过实体查找 dto 中的所有“缺失”和“额外”字段?
【发布时间】:2023-01-12 03:42:15
【问题描述】:

我需要使用反射为每个 dto 的实体找到所有“缺失”和额外的字段。 例如。

我有

public class TestDto {
  long id;
  String name;
  int age;
  long personId;
  String phone;
}

和实体

public class TestEntity {
  long id;
  String name;
  int age;
  Person person;
  String address;
}

person = personId(映射)。我们不需要像“缺失”字段和“额外”字段那样打印它。

输出: dto 缺少字段。请添加!:地址; dto 的额外字段。请删除! : 电话;

我写

private final Map<String, String> fieldMappings = new HashMap<>();

      fieldMappings.put("person", "personId"); 

      Field[] dtoFields = auditDtoClass.getDeclaredFields();
      Field[] entityFields = entityClass.getDeclaredFields();

      List<String> missingFields = Arrays.stream(entityFields)
          .filter(field -> !fieldMappings.containsKey(field.getName()) && Stream.of(dtoFields)
              .noneMatch(dtoField -> dtoField.getName().equals(field.getName())))
          .map(Field::getName)
          .filter(field -> Arrays.stream(dtoFields)
              .noneMatch(f -> f.getName().equals(field)))
          .toList();

      List<String> extraFields = Arrays.stream(dtoFields)
          .filter(field -> !fieldMappings.containsValue(field.getName()) &&
              !fieldMappings.containsKey(field.getName()) && Stream.of(entityFields)
              .noneMatch(entityField -> entityField.getName().equals(field.getName())))
          .map(Field::getName)
          .filter(field -> Arrays.stream(entityFields)
              .noneMatch(f -> f.getName().equals(field)))
          .toList();

这是不对的。

因为程序员可以在不添加到 dto 的情况下在其他实体中添加(私有 Person person 字段),并且它没有在缺少的字段中打印它。

我还认为我们可以链接这些字段 fieldMappings.put("person", "personId"); 实体/dto 类,但现在我不明白如何。 我很想听听有关如何执行此操作的想法。

【问题讨论】:

  • 使用fieldMappings.put("person", "personId");,此代码确实可以正常工作。我在这里看不到您的实际问题
  • 旁注:getDeclaredFields() 将只返回在类本身中声明的字段,而不是在超类中声明的任何字段。此外,也许您可​​以使用任何现有的映射库来查找这些差异,例如Dozer、Mapstruct 等 - 无论如何,您都必须有一些映射代码才能获取数据(例如personId = person.getId()),所以我会将该检查逻辑放入相同的功能中。
  • 我想检查所有的 dto。不仅是 TestDto 。如果您想为另一个 dto 添加人员字段,则此代码是错误的。例如 Shop 实体有字段 person 并且它只是在缺少的字段中忽略它。
  • @Thomas 我有@Mapping(source = "person.id", target = "personId") TestDto toAuditDto(Test entity);
  • 顺便说一句,您的代码似乎效率极低,例如您基本上是在遍历每个实体字段的每个 dto 字段,反之亦然,从而获得 O(n*m) 复杂性。此外,您似乎基本上过滤了两次,即 Stream.of(dtoFields).noneMatch(dtoField -&gt; dtoField.getName().equals(field.getName()))Arrays.stream(dtoFields).noneMatch(f -&gt; f.getName().equals(field)) 似乎在做同样的事情。

标签: java unit-testing reflection


【解决方案1】:

这应该可以解决问题。请根据您的需要优化代码。

{
    Map<String, Class<?>> testDtoDeclarationMap = getFieldDeclarationMap(new TestDto());
    Map<String, Class<?>> testEntityDeclarationMap = getFieldDeclarationMap(new TestEntity());

    testDtoDeclarationMap.forEach(((k, v) -> {
        if (!(testEntityDeclarationMap.containsKey(k) || testDtoDeclarationMap.get(k) == testEntityDeclarationMap.get(k))) {
            System.out.println("Extra fields for dto. Please remove!: '" + k + "' with the datatype: " + v);
        }
    }));

    testEntityDeclarationMap.forEach(((k, v) -> {
        if (!(testDtoDeclarationMap.containsKey(k) || testEntityDeclarationMap.get(k) == testDtoDeclarationMap.get(k))) {
            System.out.println("Missing fields for dto. Please add!: '" + k + "' with the datatype: " + v);
        }
    }));
}

Map<String, Class<?>> getFieldDeclarationMap(Object obj) {
    Map<String, Class<?>> map = new HashMap<>();
    Field[] declaredFields = obj.getClass().getDeclaredFields();
    for (int x=0; x<declaredFields.length; x++) {
        Field field = declaredFields[x];
        String name = field.getName();
        Class<?> type = field.getType();
        map.put(name, type);
    }
    return map;
}

【讨论】:

    猜你喜欢
    • 2023-01-08
    • 2021-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-17
    • 2021-10-28
    • 1970-01-01
    • 2015-09-02
    相关资源
    最近更新 更多