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

如何用Mapstruct实现MyOM与MyEntity父子结构列表的双向映射?

使用MapStruct实现List与List的双向映射

场景说明

MyOM采用树形结构:父节点包含子节点集合,子节点无下级节点;MyEntity采用扁平结构:通过parent字段关联父实体,根实体的parent为null。需要实现两种结构列表的双向转换。

实体与DTO定义

类结构如下:

class MyOM {
    private String label;
    private Set<MyOM> children;
    // 省略getter、setter、构造方法
}

class MyEntity {
    private String label;
    private MyEntity parent;
    // 省略getter、setter、构造方法
}

映射实现(Mapper接口)

MapStruct无法自动处理树形与扁平结构的转换,需结合自定义逻辑实现:

@Mapper(config = ServiceMapperConfig.class)
public interface IMyObjectMapper {

    // 基础转换:单个MyEntity → MyOM
    MyOM entityToOm(MyEntity entity);

    // 基础转换:单个MyOM → MyEntity
    MyEntity omToEntity(MyOM om);

    // MyEntity列表 → MyOM列表:组装树形结构
    default List<MyOM> mapEntities(List<MyEntity> entities) {
        // 按父节点分组,快速查找子节点
        Map<MyEntity, List<MyEntity>> parentToChildren = entities.stream()
                .filter(e -> e.getParent() != null)
                .collect(Collectors.groupingBy(MyEntity::getParent));

        // 处理所有根节点(parent为null),构建树形结构
        return entities.stream()
                .filter(e -> e.getParent() == null)
                .map(this::buildOmTree)
                .collect(Collectors.toList());
    }

    // 构建单个MyOM树形节点
    default MyOM buildOmTree(MyEntity parentEntity) {
        MyOM parentOm = entityToOm(parentEntity);
        // 查找并转换当前父实体的子节点
        List<MyEntity> childEntities = parentToChildren.getOrDefault(parentEntity, Collections.emptyList());
        Set<MyOM> childOms = childEntities.stream()
                .map(this::entityToOm)
                .collect(Collectors.toSet());
        parentOm.setChildren(childOms);
        return parentOm;
    }

    // MyOM列表 → MyEntity列表:拆解树形为扁平结构
    default List<MyEntity> mapOMs(List<MyOM> oms) {
        List<MyEntity> entities = new ArrayList<>();
        // 遍历所有根OM,处理自身及子节点
        for (MyOM rootOm : oms) {
            processOmNode(rootOm, null, entities);
        }
        return entities;
    }

    // 处理单个MyOM节点,转换为Entity并设置父节点
    default void processOmNode(MyOM om, MyEntity parentEntity, List<MyEntity> entities) {
        MyEntity entity = omToEntity(om);
        entity.setParent(parentEntity);
        entities.add(entity);
        // 处理子节点(子节点无后代,直接遍历)
        if (om.getChildren() != null) {
            for (MyOM childOm : om.getChildren()) {
                processOmNode(childOm, entity, entities);
            }
        }
    }
}

代码说明

  1. MyEntity → MyOM:

    • 先通过流式API将子实体按父实体分组,避免重复遍历查找
    • 筛选出根实体(parent为null),逐个构建树形结构,为每个父OM添加对应子OM集合
  2. MyOM → MyEntity:

    • 遍历每个根OM,递归处理自身及所有子OM
    • 转换每个OM为Entity时,设置对应父Entity,最终收集所有Entity到扁平列表中

注意事项

  • 确保实体类的getter/setter方法齐全,MapStruct依赖这些方法完成属性映射
  • 若子节点存在多层嵌套,上述递归逻辑可兼容多层场景
  • 数据量较大时,递归可能引发栈溢出,可将递归改为迭代实现

内容的提问来源于stack exchange,提问作者jeangr

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 02:45:39