Mapstruct如何从源对象的2个或更多字段构造目标对象?

时间:2019-05-07 19:07:23

标签: java mapstruct

class PersonDTO {
  String name;
  String street;
  String city;
}
class Person {
  String name;
  Address address;
}
class Address {
  String street;
  String city;
}

@Mapper(componentModel = "spring")
interface Mapper {
  Person fromPersonDTO(PersonDTO dto);
}

我尝试使用2 StringAddress,但它抛出

  

模糊属性异常

我应该在映射器中添加些什么,以将street中的cityPersonDTO映射到Address

更新:

@Mapper(componentModel = "spring")
interface Mapper {
  @Mapping(source = "street", target = "address.street")
  @Mapping(source = "city", target = "address.city")
  Person fromPersonDTO(PersonDTO dto);
}

以上映射器可以处理直接映射。 但是,如果我在创建Address对象

时想添加一些业务逻辑怎么办?

例如:

address.street = street.replaceAll(" ", "_"); 
address.city = cityDao.findByName(city).getId();

有没有办法达到这种要求?

1 个答案:

答案 0 :(得分:1)

@Mapper(componentModel = "spring")
interface Mapper {

    @Mappings({
            @Mapping(source = "street", target = "address.street"),
            @Mapping(source = "city", target = "address.city")
    })
    Person fromPersonDTO(PersonDTO dto);
}

属性name应该自动映射,只要它具有相同的名称和嵌套级别

更新

@Mapper(componentModel = "spring")
public abstract class Mapper {

    @Autowired
    private CityDAO cityDao;

    @Mappings({
            @Mapping(source = "street", target = "address.street"),
            @Mapping(source = "city", target = "address.city")
    })
    Person fromPersonDTO(PersonDTO dto);

    @AfterMapping
    void after(@MappingTarget Person person) {
        Address address = person.getAddress();
        if (address != null) {
            // additional null-checks might be required
            address.setStreet(address.getStreet().replaceAll(" ", "_")); 
            address.setCity(cityDao.findByName(address.getCity()).getId();
        }
    }
}

请注意,要使用自动装配的bean,映射器必须是类,而不是接口