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

使用MapStruct实现不同属性类映射的问题求助

MapStruct 对象映射正确实现方案

首先明确核心映射逻辑:

  • DataEntity → DataDomain:DataEntity的codDist/numFun要传递给每个Domain,同时将DataEntity的pares列表中每个ParEntity转换为Domain对象(补充DataEntity的公共字段)
  • DataDomain → DataEntity:取DataDomain中第一个Domain对象,将其公共字段赋值给DataEntity,再将Domain的剩余字段转换为ParEntity放入DataEntity的pares列表

修正后的Mapper实现

import org.mapstruct.Mapper;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Mapper
public interface ParOutMapper {

    ParOutMapper INSTANCE = Mappers.getMapper(ParOutMapper.class);
    DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE_TIME; // 根据实际格式调整

    // DataEntity 转 DataDomain
    @Mapping(target = "data", source = "entity", qualifiedByName = "entityToDomainList")
    DataDomain map(DataEntity entity);

    // 核心:将DataEntity的公共字段+每个ParEntity的字段转换为Domain
    @Named("entityToDomainList")
    default List<Domain> entityToDomainList(DataEntity entity) {
        if (entity == null || entity.getPares() == null) {
            return new ArrayList<>();
        }
        return entity.getPares().stream()
                .map(par -> {
                    Domain domain = new Domain();
                    // 赋值DataEntity的公共字段
                    domain.setCodDist(entity.getCodDist());
                    domain.setNumFun(entity.getNumFun());
                    // 映射ParEntity到Domain的字段
                    domain.setTxtJust(par.getTxtJus());
                    domain.setValPar(indValParToBoolean(par.getIndValPar()));
                    domain.setDateHr(stringToLocalDateTime(par.getDateHr()));
                    domain.setNumPn(stringToInteger(par.getNumPn()));
                    return domain;
                })
                .collect(Collectors.toList());
    }

    // DataDomain 转 DataEntity
    default DataEntity map(DataDomain domain) {
        if (domain == null || domain.getData() == null || domain.getData().isEmpty()) {
            return null;
        }
        Domain firstDomain = domain.getData().get(0);
        DataEntity entity = new DataEntity();
        // 赋值公共字段
        entity.setCodDist(firstDomain.getCodDist());
        entity.setNumFun(firstDomain.getNumFun());
        // 将Domain转换为ParEntity放入pares列表
        ParEntity parEntity = new ParEntity();
        parEntity.setTxtJus(firstDomain.getTxtJust());
        parEntity.setIndValPar(booleanToIndValPar(firstDomain.getValPar()));
        parEntity.setDateHr(localDateTimeToString(firstDomain.getDateHr()));
        parEntity.setNumPn(integerToString(firstDomain.getNumPn()));
        parEntity.setNumFun(firstDomain.getNumFun()); // 按需同步numFun字段
        entity.setPares(List.of(parEntity));
        return entity;
    }

    // 自定义类型转换方法
    @Named("indValParToBoolean")
    default Boolean indValParToBoolean(String indValPar) {
        return Objects.equals(indValPar, "Y") || Objects.equals(indValPar, "1"); // 根据实际业务规则调整
    }

    @Named("booleanToIndValPar")
    default String booleanToIndValPar(Boolean valPar) {
        return valPar != null && valPar ? "Y" : "N"; // 对应上面的转换规则
    }

    @Named("stringToLocalDateTime")
    default LocalDateTime stringToLocalDateTime(String dateHr) {
        return dateHr != null ? LocalDateTime.parse(dateHr, DATE_TIME_FORMATTER) : null;
    }

    @Named("localDateTimeToString")
    default String localDateTimeToString(LocalDateTime dateHr) {
        return dateHr != null ? dateHr.format(DATE_TIME_FORMATTER) : null;
    }

    @Named("stringToInteger")
    default Integer stringToInteger(String numPn) {
        return numPn != null ? Integer.valueOf(numPn) : null;
    }

    @Named("integerToString")
    default String integerToString(Integer numPn) {
        return numPn != null ? numPn.toString() : null;
    }

    // 批量转换List<DataEntity>到List<Domain>
    default List<Domain> toDomainList(List<DataEntity> entityList) {
        if (entityList == null) {
            return new ArrayList<>();
        }
        return entityList.stream()
                .flatMap(entity -> entityToDomainList(entity).stream())
                .collect(Collectors.toList());
    }
}

关键说明

  1. 结构适配:由于DataEntity和DataDomain的列表维度不匹配(DataEntity是单对象+子列表,DataDomain是子对象列表),必须通过default方法手动处理结构转换,无法完全依赖MapStruct的自动映射。
  2. 类型转换:针对字符串转布尔、日期、数字的场景,定义了命名转换方法,保证映射逻辑的可维护性。
  3. 空值处理:所有转换逻辑都加入了空值判断,避免空指针异常。
  4. 业务规则调整:如果numFun需要从ParEntity取而非DataEntity,直接修改entityToDomainList中的domain.setNumFun(par.getNumFun())即可;日期格式可根据实际业务场景调整DATE_TIME_FORMATTER。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 02:39:09