MapStruct列表映射中如何将父对象传递给子对象映射器
MapStruct映射子对象时访问父对象字段的解决方案
问题场景
使用MapStruct 1.5.3进行实体与DTO映射时,需在子对象(Child→ChildDto)的映射过程中访问父对象(Parent)的字段,拼接生成ChildDto的valueWithName属性。尝试通过@Context传递父对象给子映射器时,出现编译错误:
Example.java:44:19 java: Unmapped target property: "valueWithName". Mapping from Collection element "Example.Child children" to "Example.ChildDto children".
错误原因
当MapStruct自动处理Parent到ParentDto的children列表映射时,默认会调用无@Context参数的Child→ChildDto映射方法,而该方法无法获取父对象字段来生成valueWithName,导致MapStruct无法识别该属性的映射逻辑,抛出未映射属性错误。
解决方案
方案一:通过@Context显式传递父对象(推荐)
修改Mapper接口,在父对象映射时,指定子列表的映射方法,并传递父对象作为@Context参数:
@Mapper public interface MyMapper { // 映射Parent到ParentDto,指定children使用带父对象上下文的映射方法 @Mapping(target = "children", source = "children", qualifiedByName = "mapChildrenWithParent") ParentDto map(Parent parent); // 自定义子列表映射方法,接收父对象作为上下文 @Named("mapChildrenWithParent") default List<ChildDto> mapChildren(List<Child> children, @Context Parent parent) { return children.stream() .map(child -> mapChild(child, parent)) .collect(Collectors.toList()); } // 子对象映射方法,通过@Context获取父对象 @Mapping(target = "valueWithName", source = "child", qualifiedByName = "getValueWithName") ChildDto mapChild(Child child, @Context Parent parent); // 生成valueWithName的逻辑,结合子对象和父对象字段 @Named("getValueWithName") default String getValueWithName(Child child, @Context Parent parent) { return child.getValue() + parent.getName(); } }
方案二:使用@AfterMapping事后补全
先完成基础映射,再在父对象映射完成后,遍历子列表补全valueWithName属性:
@Mapper public interface MyMapper { // 基础映射:Parent→ParentDto,Child→ChildDto(此时ChildDto的valueWithName未填充) ParentDto map(Parent parent); ChildDto mapChild(Child child); // 父对象映射完成后,补全子对象的valueWithName @AfterMapping default void afterMapParent(Parent parent, @MappingTarget ParentDto parentDto) { List<Child> children = parent.getChildren(); List<ChildDto> childDtos = parentDto.getChildren(); for (int i = 0; i < children.size(); i++) { Child child = children.get(i); ChildDto childDto = childDtos.get(i); childDto.setValueWithName(child.getValue() + parent.getName()); } } }
验证结果
两种方案均可实现需求,运行原main方法后,输出结果为:
a ba
内容的提问来源于stack exchange,提问作者mkczyk
相关产品推荐
相关产品推荐

