ModelMapper:匹配多个源属性层次结构

31

我无法解决modelMapper错误。你有任何想法问题出在哪里吗?

NB:由于java.sql.Time没有无参构造函数,我找不到更好的方法,只能编写转换器。

org.modelmapper.ConfigurationException: ModelMapper configuration errors:

1) The destination property 
biz.models.CarWash.setSecondShift()/java.util.Date.setTime() matches 
multiple source property hierarchies:

biz.dto.CarWashDTO.getFirstShift()/java.time.LocalTime.getSecond()
biz.dto.CarWashDTO.getSecondShift()/java.time.LocalTime.getSecond()

这个错误是由这段代码造成的

@SpringBootTest
@RunWith(SpringRunner.class)
public class CarWashDTO2CarWash {

@Autowired
protected ModelMapper modelMapper;

@Test
public void testCarWashDTO2CarWash_allFiledShouldBeConverted(){
    CarWashDTO dto = CarWashDTO.builder()
            .name("SomeName")
            .address("SomeAddress")
            .boxCount(2)
            .firstShift(LocalTime.of(9, 0))
            .secondShift(LocalTime.of(20, 0))
            .phoneNumber("5700876")
            .build();

    modelMapper.addConverter((Converter<CarWashDTO, CarWash>) mappingContext -> {
        CarWashDTO source = mappingContext.getSource();
        CarWash destination = mappingContext.getDestination();
        destination.setId(source.getId());
        destination.setFirstShift(source.getFirstShift() == null ? null : Time.valueOf(source.getFirstShift()));
        destination.setSecondShift(source.getSecondShift() == null ? null : Time.valueOf(source.getSecondShift()));
        destination.setEnable(true);
        destination.setAddress(source.getAddress());
        destination.setBoxCount(source.getBoxCount());
        destination.setName(source.getName());
        destination.setDateOfCreation(source.getDateOfCreation());
        return destination;
    });

    final CarWash entity = modelMapper.map(dto, CarWash.class);
    assertNotNull(entity);
    assertEquals(2, entity.getBoxCount().intValue());
    assertEquals("SomeAddress", entity.getAddress());
    assertEquals("SomeName", entity.getName());
}

Modelmapper Bean是由以下配置构建的

@Bean
public ModelMapper modelMapper(){
    return new ModelMapper();
}

数据传输对象:

public class CarWashDTO {
private Long id;
private String name;
private String address;
private String phoneNumber;
private Integer boxCount;
private LocalTime firstShift;
private LocalTime secondShift;
private LocalDateTime dateOfCreation;
}

实体(firstShift和secondShift为java.sql.Time类型):

public class CarWash {
private Long id;
private String name;
private String address;
private String phoneNumber;
private Integer boxCount;
private Time firstShift;
private Time secondShift;
private LocalDateTime dateOfCreation;
private Boolean enable;
private Owner owner;
}
5个回答

49

尝试使用modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT)


4
这是最佳答案。但我仍然看到有冲突的情况:modelMapper.getConfiguration().setAmbiguityIgnored(true);(该代码是Java代码,表示设置ModelMapper对象的配置选项,忽略模型映射时的歧义问题。) - David J Barnes
modelMapper.getConfiguration().setAmbiguityIgnored(true) 跳过了值的设置器。但 modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT) 设置了最佳匹配的值。这对我很有效。 - Sudarshani Perera
1
严格的策略并不能帮助解决问题,如果这样做,将不会有任何异常,但设置的值将为null或零。确切的解决方案是在模型映射器的配置中设置歧义检查,以检查重复匹配。 - Learn More

26
这解决了我的问题: modelMapper.getConfiguration().setAmbiguityIgnored(true);

2
这个配置只会让ModelMapper跳过该字段。在这种情况下,CarWashDTO.id字段在映射后将为null。 - socona
1
这对我有用,首先我做了以下四步:1)mapper.getConfiguration().setAmbiguityIgnored(true);然后配置了typeMap 2)mapper.createTypeMap(...).addMappings();之后设置了3)mapper.getConfiguration().setAmbiguityIgnored(false);最后4)mapper.validate()。 - Elazar Neeman
1
这对我没用,返回 null。但下面的答案有效。 - mohkamfer

5

在Bean初始化期间,您需要使用PropertyMap自定义ModelMapper配置:

http://modelmapper.org/user-manual/property-mapping/
@Bean
public ModelMapper modelMapper(){
    ModelMapper mm = new ModelMapper();

    PropertyMap<CarWashDTO, CarWash> propertyMap = new PropertyMap<CarWashDTO, CarWash> (){
        protected void configure() {
            map(source.getId()).setId(null);
        }
    }

    mm.addMappings(propertyMap);
    return mm;
}

1

我不确定在问这个问题时 ModelMapper 是如何处理的,但使用转换器应该很简单。不要为整个类实现转换器,而是将其实现到实际需要转换的类型上。就像这样:

public static Converter<LocalTime, Time> timeConverter = new AbstractConverter<>() {
    @Override
    protected Time convert(LocalTime source) {
        return null == source ? null : Time.valueOf(source);
    }
}; 

然后就是:
mm.addConverter(timeConverter);

如果你使用Spring或EJB,你应该知道如何将它添加到你的配置中。


0

这解决了我的问题:

modelMapper.getConfiguration().setAmbiguityIgnored(true);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接