使用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()); } }
关键说明
- 结构适配:由于DataEntity和DataDomain的列表维度不匹配(DataEntity是单对象+子列表,DataDomain是子对象列表),必须通过
default方法手动处理结构转换,无法完全依赖MapStruct的自动映射。 - 类型转换:针对字符串转布尔、日期、数字的场景,定义了命名转换方法,保证映射逻辑的可维护性。
- 空值处理:所有转换逻辑都加入了空值判断,避免空指针异常。
- 业务规则调整:如果
numFun需要从ParEntity取而非DataEntity,直接修改entityToDomainList中的domain.setNumFun(par.getNumFun())即可;日期格式可根据实际业务场景调整DATE_TIME_FORMATTER。
内容的提问来源于stack exchange,提问作者user19573093
相关产品推荐
相关产品推荐

