Several possible source properties for target property "address"

Viewed 3601
@Mapper(componentModel = "spring", injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public abstract class FooMapper {

    @Autowired
    static AddressMapper addressMapper;

    @Mapping(source = "entity.id", target = "id")
    @Mapping(target = "address", qualifiedByName = "mappingAddress")
    public abstract FooEntity dtoAndEntityToEntity(FooDto dto, FooEntity entity);
    
    @Named("mappingAddress")
    static AddressEntity mappingAddress(FooDto dto, FooEntity entity) {
        if (Objects.nonNull(dto) && Objects.nonNull(dto.getAddress())) {
            return addressMapper.dtoToEntity(dto.getAddress());
        }
        if (Objects.nonNull(entity)) {
            return entity.getAddress();
        }
        return null;
    }
}

I want to map the address even from entity of dto, if dto is null, I should to use entity info, I used that custom method, but I got and error :

Error:(27,41) java: Several possible source properties for target property "address".

The error is clear, the error happen because entity and dto have address attribute, but I don't want to set the source, I want it to be deducted from entity or dto.

Is there any way to avoid this error please?

1 Answers

I see several issues in your solution.. Do you require a mapping target (as update method?). Then you need the method argument like that.( Note I personally leave the result void in those cases).

Then: you only need a qualifiedBy if you've got a selection conflict. So, in essence if you have multiple methods with the same signature for MapStruct to choose from.

Finally, you need to indicate that it's the whole object you are considering.


@Mapper(componentModel = "spring", injectionStrategy = InjectionStrategy.CONSTRUCTOR)
public abstract class FooMapper {

    //@Autowired not sure whether you should use a static field for this, perhaps you should inject it at the place where you are going to use the mapper.
    // static AddressMapper addressMapper;

    @Mapping(source = "entity.id", target = "dto.id")
    @Mapping(target = "address", source = "dto" )
    public abstract void dtoAndEntityToEntity(FooDto dto, @MappingTarget FooEntity entity);
    

    // why was this method static? The mapper itself is already by design a singleton.
    @Named("mappingAddress")
    void mappingAddress(FooDto dto, @MappingTarget FooEntity entity) {
        if (Objects.nonNull(dto) && Objects.nonNull(dto.getAddress())) {
            addressMapper.dtoToEntity(dto.getAddress());
        }
        if (Objects.nonNull(entity)) {
            entity.getAddress();
        }
    }
}

Related