首页 > 解决方案 > 使用转换器和提供者而不是属性映射时如何让 ModelMapper.validate() 成功?

问题描述

有类似的东西:

@Getter @Setter
public static class Entity {
    private int hash;
    private LocalDateTime createdTime;
}

@Getter @Setter
public static class DTO {
    private String hash;
    private String createdTime;
}

我需要双向映射,所以我应该能够映射Entity -> DTO -> Entity。在这个例子中,属性类型恰好是LocalDateTime但可能是任何需要解析的类型String(只是说我不是在寻求更好的映射方式,LocalDateTime而是在一般情况下)。

映射没有问题。我 create TypeMap、 addConverter和 for LocalDateTimeaProvider也是因为它确实有公共默认构造函数。像这里的东西。

如果我的 DTO 也有LocalDateTime createdTime(或String createdTime我的Entity),那么我ModelMapper.validate()会很高兴。但我没有,我需要创建所有转换的东西。

这一切都导致ModelMapper.validate()抱怨:

Unmapped destination properties found in TypeMap[DTO -> Entity]:  
    org.example.test.modelmapper.validation.TestIt$Entity.setCreatedTime()

我目前用于验证LocalDateTime案例映射的代码是:

ModelMapper mm = new ModelMapper();
mm.createTypeMap(Entity.class, DTO.class);
mm.createTypeMap(DTO.class, Entity.class);
mm.createTypeMap(String.class, LocalDateTime.class)
        .setPropertyProvider(localDateTimeProvider);
mm.addConverter(toStringDate);
mm.validate();

(所以我没有做任何实际的映射,而是验证映射)

Provider<LocalDateTime> localDateTimeProvider =
        new AbstractProvider<LocalDateTime>() {
    @Override
    public LocalDateTime get() {
        return LocalDateTime.now();
    }
};

Converter<String, LocalDateTime> toStringDate = new AbstractConverter<>() {
    @Override
    protected LocalDateTime convert(String source) {
        return LocalDateTime.parse(source);
    }
};

询问更多细节/代码。我会根据需要更新问题

标签: javamappingdtoconvertersmodelmapper

解决方案


setPropertyProvider方法允许指定一个 Provider 用于在 TypeMap 中提供映射属性的实例。

所以当你写:

mm.createTypeMap(String.class, LocalDateTime.class)
        .setPropertyProvider(localDateTimeProvider);

它不适合这种情况,因为我们没有在将 String 类型的属性映射到 LocalDateTime 类型的属性时使用此提供程序。它应该移到上面以与DTO -> Entity TypeMap 相关联(顺便说一下,错误消息是一个很好的提示)。所以应该是这样。

mm.createTypeMap(DTO.class, Entity.class)
                .setPropertyProvider(localDateTimeProvider);

这很有意义,因为我们使用提供程序来提供实例,用于将 DTO ( String createdTime;) 的 String 属性映射到 Entity () 的 LocalDateTime 属性LocalDateTime createdTime;

另一方面,转换器应该在相应的提供者之前添加到 ModelMapper 中。

同样离开mm.createTypeMap(String.class, LocalDateTime.class),我的编译器抱怨类似的类型映射已经存在,不需要创建一个新的。因此,我可以丢弃它。

通过这两个更改,我的 bean 看起来像:

@Bean
ModelMapper demoModelMapper() {

   Provider<LocalDateTime> localDateTimeProvider =
   new AbstractProvider<LocalDateTime>() {
      @Override
      public LocalDateTime get() {
         return LocalDateTime.now();
      }
   };

   Converter<String, LocalDateTime> toStringDate = new AbstractConverter<String, 
   LocalDateTime>() {
      @Override
      protected LocalDateTime convert(String source) {
         return LocalDateTime.parse(source);
      }
   };

   ModelMapper mm = new ModelMapper();


   mm.createTypeMap(Entity.class, DTO.class);
   mm.addConverter(toStringDate);
   mm.createTypeMap(DTO.class, Entity.class)
     .setPropertyProvider(localDateTimeProvider);
   mm.validate();

   return mm;
}

请注意,我在返回 bean 之前调用了validate() 。这对我有用。请测试并在您身边查看。


推荐阅读