使用 @aftermapping 进行 MapStruct 批量转换

nvp*_*152 2 mapstruct

我想在 DTO 的单项转换之后使用专用的 @AfterMapping 来应用装饰,并在处理其集合转换风格时使用另一个专用的 @AfterMapping,但不能同时使用两者。

public abstract CatUI convert(Cat cat);
public abstract List<CatUI> convert(List<Cat> cats);


@AfterMapping
public void populateCatName(Cat cat, @MappingTarget CatUI catUI) {
     String name = _someRemoteService.getCatName(catUI.getId());
     catUI.setName(name);
}

@AfterMapping
public void populateCatNames(List<Cat> cats, @MappingTarget List<CatUI> catUIs) {
     Map<Integer,String> idToNameMap = _someRemoteService.getCatNames(catUIs.stream().map((c) -> c.getId() ).collect(Collectors.toList());
     catUIs.forEach((c) -> c.setName(idToNameMap(c.getId())));
}
Run Code Online (Sandbox Code Playgroud)

我不希望在处理列表转换时调用 populateCatName ,从而重复我的装饰。

无论如何要这样做吗?

Fil*_*lip 5

使用 1.1.0.Final 时,您必须定义 2 个入口点(映射器),一个在列表中包含转换,另一个不包含列表中的转换。

我建议您尝试一下新的 1.2.0.Beta2。有了它,您就可以使用新的@Context.

你可以有这样的界面:

public interface CatMappingContext {

    @AfterMapping
    public default void populateCatName(Cat cat, @MappingTarget CatUI catUI) {
        //nothing per default
    }

    @AfterMapping
    public void populateCatNames(List<Cat> cats, @MappingTarget List<CatUI> catUIs) {
        //nothing per default
    }
}
Run Code Online (Sandbox Code Playgroud)

和2个实现:

public class SingleMappingContext implements CatMappingContext {

    @AfterMapping
    public void populateCatName(Cat cat, @MappingTarget CatUI catUI) {
        String name = _someRemoteService.getCatName(catUI.getId());
        catUI.setName(name);
    }
}

public class ListMappingContext implements CatMappingContext {

    @AfterMapping
    public void populateCatNames(List<Cat> cats, @MappingTarget List<CatUI> catUIs) {
        Map<Integer,String> idToNameMap = _someRemoteService.getCatNames(catUIs.stream().map((c) -> c.getId() ).collect(Collectors.toList());
        catUIs.forEach((c) -> c.setName(idToNameMap(c.getId())));
    }
}
Run Code Online (Sandbox Code Playgroud)

最后你的映射器看起来像:

public interface CatMapper {

    public CatUI convert(Cat cat, @Context CatMappingContext context);
    public List<CatUI> convert(List<Cat> cats, @Context CatMappingContext context);
}
Run Code Online (Sandbox Code Playgroud)

然后,您需要使用上下文SingleMappingContextListMappingContext.