Mapstruct结合Lombok @Builder多源嵌套对象映射问题
MapStruct + Lombok @Builder 多源映射嵌套字段未填充问题解决
问题场景
使用MapStruct从JmsMessageKpiDto和KpiDto两个源对象构建带嵌套KpiMeta的Kpi对象,Kpi和KpiMeta均使用Lombok的@Builder注解。已通过@Mapper(uses = KpiMetaMapper.class)引入负责生成KpiMeta的映射器,但生成的代码中Kpi的meta字段始终未被填充。
可行解决方案
1. 显式指定嵌套字段的映射规则
在KpiMapper的映射方法中,通过@Mapping注解明确指定meta字段的映射逻辑,调用KpiMetaMapper中的多参数映射方法:
首先给KpiMetaMapper的映射方法添加@Named标识:
@Mapper interface KpiMetaMapper { KpiMetaMapper INSTANCE = Mappers.getMapper(KpiMetaMapper.class); @Named("toKpiMeta") KpiMeta toKpiMeta(JmsMessageKpiDto jms, KpiDto dto); }
然后在KpiMapper中关联该方法:
@Mapper(uses = KpiMetaMapper.class) interface KpiMapper { KpiMapper INSTANCE = Mappers.getMapper(KpiMapper.class); @Mapping(target = "name", source = "dto.name") @Mapping(target = "meta", source = ".", qualifiedByName = "toKpiMeta") Kpi toKpi(JmsMessageKpiDto jms, KpiDto dto); }
这里source = "."表示将所有源参数(即jms和dto)传递给qualifiedByName指定的方法,MapStruct会自动匹配参数类型完成映射。
2. 调整Kpi的Builder配置(避免Builder冲突)
MapStruct在处理Lombok的@Builder时,有时会因为Builder的参数顺序或默认生成逻辑导致嵌套字段映射失效。可以给Kpi类的@Builder添加toBuilder = true,确保MapStruct能正确触发Builder的字段填充逻辑:
@Builder(toBuilder = true) class Kpi { String name; KpiMeta meta; }
3. 已验证有效的@AfterMapping兜底方案
如果上述方案不适用,@AfterMapping是最直接的兜底方案,手动在映射后填充meta字段:
@Mapper(uses = KpiMetaMapper.class) interface KpiMapper { KpiMapper INSTANCE = Mappers.getMapper(KpiMapper.class); @Mapping(target = "meta", ignore = true) Kpi toKpi(JmsMessageKpiDto jms, KpiDto dto); @AfterMapping default void fillKpiMeta(JmsMessageKpiDto jms, KpiDto dto, @MappingTarget Kpi.KpiBuilder kpiBuilder) { kpiBuilder.meta(KpiMetaMapper.INSTANCE.toKpiMeta(jms, dto)); } }
这里先忽略meta的自动映射,再通过@AfterMapping调用KpiMetaMapper的方法,手动给Builder设置meta字段。
内容的提问来源于stack exchange,提问作者Bapt_
相关产品推荐
相关产品推荐

