MapStruct如何将源对象父级字段映射到目标对象子集合对应字段
MapStruct 映射实现最优方案
首先需要确保三个实体类都已添加对应的getter、setter方法(可直接用Lombok的@Data注解简化开发),实体类定义如下:
class Item { String oneTo; // 需补充getter、setter方法 } class Header { String twoTo; List<Item> items; // 需补充getter、setter方法 } class HeaderFrom { String oneFrom; String twoFrom; // 需补充getter、setter方法 }
实现方案
最优方案采用@Mapping完成单字段映射 + @AfterMapping回调完成集合批量赋值,兼顾可读性、可维护性和性能,代码示例如下:
import org.mapstruct.AfterMapping; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.MappingTarget; import java.util.Objects; // 如果使用Spring框架,可添加componentModel = "spring"配置,直接注入Mapper使用 @Mapper(componentModel = "spring") public interface HeaderMapper { // 基础字段映射规则:twoFrom 映射到 Header的twoTo属性 @Mapping(source = "twoFrom", target = "twoTo") Header toHeader(HeaderFrom source); // 重载方法:支持从外部传入已有的items列表 @Mapping(source = "source.twoFrom", target = "twoTo") Header toHeader(HeaderFrom source, List<Item> items); // 映射完成后的回调方法,批量给所有Item的oneTo属性赋值 @AfterMapping default void fillItemOneTo(HeaderFrom source, @MappingTarget Header target) { // 判空处理避免空指针异常 if (Objects.isNull(source) || Objects.isNull(target.getItems())) { return; } // 遍历items列表统一赋值 target.getItems().forEach(item -> item.setOneTo(source.getOneFrom())); } }
方案优势
- 基础字段映射直接复用MapStruct原生能力,无需手动编写赋值代码,性能和可靠性有官方保证
- 集合批量赋值逻辑独立在回调方法中,代码逻辑清晰,调试和修改都非常方便,比在
@Mapping中写SpEL表达式的可读性和可维护性高很多 - 兼容两种常用场景:如果
Header实例化时已经初始化了items列表,直接调用单参数转换方法即可;如果items需要从外部传入,直接调用双参数重载方法即可 - 自带空指针防护,覆盖边界场景
内容的提问来源于stack exchange,提问作者Hasith Magage
相关产品推荐
相关产品推荐

