You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 07:40:33