简体   繁体   中英

mapstruct service mapping in a collection

I have a parent with a collection of children that I want to map.

Parent -> Collection<Child> children
ParentDTO -> Collection<ChildDTO> childDTOs

From DTO to Domain I want a database lookup call: I have a service method that looks-up a child on it's id:

Child getChild(Long id)

Now in the parent dtoToDomain(parentDTO) I want mapstruct to do a lookup for each item in the collection.

This solution works for single-occ, mapstruct can find getChild in the service and writes the lookup action:

@Mapper(uses = ChildService.class)
public interface ParentMapper {

    @Mapping(source="child.id", target="child")
    Parent dtoToDomain(ParentDTO parentDTO);
}

However, for a collection I have to specify a specific method for the collection mapping, but what do I put in the @Mapping? Something like this?

@Mapping(source="child.id", target="child")
Collection<Child> dtoToDomain(Collection<ChildDTO> children)

I do not see how I can write a default implementation since I need the service that is autowired by the implementation.

I could imagine this solution: a child mapper where I override the Dto to Domain method with a look-up like this:

@Mapper(uses = ChildMapper.class)
public interface ParentMapper {

    Parent dtoToDomain(ParentDTO parentDTO);
}

@Mapper(uses = ChildService.class)
public interface ChildMapper {

    @Mapping(source="id", target="")
    Child dtoToDomain(ChildDTO child);
}

But target is mandatory in mapstruct. Maybe I can somehow specify the entire object as target?

I presume you are looking for Object factories .

With @ObjectFactory you can create an instance for the mapping based on the source object.

For example

public class ChildFactory {


    private final ChildService childService;

    public ChildFactory(ChildService childService) {
        this.childService = childService;
    }


    public Child createChild(ChildDto dto) {
        if (dto.getId() == null) {
            return new Child();
        } else {
            return childService.findById(dto.getId());
        }
    }
}

For now you can use the ChildFactory in your ChildMapper . In the future it probably would be possible to pass the factory as a @Context . See #1398

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM