使用转换器和提供程序代替属性映射时,如何使ModelMapper.validate()成功?

问题描述 投票:3回答:2

具有类似内容:

@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,而是一般而言)。

映射没有问题。我创建了TypeMap,添加了Converter,并为LocalDateTime添加了一个Provider,因为它确实注意到具有公共默认构造函数。类似于here

如果我在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();

(因此,我没有进行任何实际的映射,但正在验证映射)

with

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);
    }
};

要求了解更多详细信息/代码。我将根据需要更新问题

java mapping dto converters modelmapper
2个回答
1
投票

setPropertyProvider方法允许指定提供程序,该提供程序用于在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属性映射到实体(LocalDateTime createdTime;)的LocalDateTime属性。

另一方面,应该在相应的提供者之前将转换器添加到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()。这对我有用。请进行测试,并在您的身边看看。


0
投票

answer from alainlompo中,我不得不在创建类型映射之前移动转换器的添加。

但是我也不得不删除提供程序部分,因为它似乎导致all字符串字段被映射为LocalDateTime,所以出现类似以下错误:

org.modelmapper.MappingException:ModelMapper映射错误:1)提供的目标实例2020-01-05T17:28:22.088694不是必需的int类型。

[我认为这意味着ModelMapper试图用代表hash的字符串填充字段LocalDateTime

似乎完全不需要提供程序。因此,我的最终代码只是添加了一个转换器:

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

这实际上意味着我提出了一个错误的问题,声称我需要使用提供程序

© www.soinside.com 2019 - 2024. All rights reserved.