MapStruct映射异常:SectionTargetingGroupIncludeExclude转List报错
问题场景
我尝试将一个SectionTargetingRule对象映射到另一个同名但结构相似的对象时,遇到MapStruct报错。它错误地尝试将SectionTargetingGroupIncludeExclude类型转换为List<TargetingTuple>类型,这与我的数据结构不符。取消注释@Mapping(target = "items", ignore = true)后映射正常,但该字段始终引发问题。
数据结构
目标类(Targets)
public class SectionTargetingGroup { public String name; public List<TargetingTuple> items; } public class SectionTargetingGroupIncludeExclude { static final SectionTargetingGroupIncludeExclude DEFAULT = new SectionTargetingGroupIncludeExclude(); public List<SectionTargetingGroup> include = Lists.newArrayList(); public List<SectionTargetingGroup> exclude = Lists.newArrayList(); } public class SectionTargetingRule extends TargetingRule { static final SectionTargetingRule DEFAULT = new SectionTargetingRule(); public int version; public SectionTargetingGroupIncludeExclude items = SectionTargetingGroupIncludeExclude.DEFAULT; }
源类(Sources)
public class SectionTargetingGroup { private String name; private List<TargetingTuple> items; } public class SectionTargetingGroupIncludeExclude { private List<SectionTargetingGroup> include; private List<SectionTargetingGroup> exclude; } public class SectionTargetingRule { private Integer version; private SectionTargetingGroupIncludeExclude items; }
错误信息
...ProfileMapper.java:147: error: Can't map property "SectionTargetingGroupIncludeExclude items" to "List<TargetingTuple> items". Consider to declare/implement a mapping method: "List<TargetingTuple> map(SectionTargetingGroupIncludeExclude value)". SectionTargetingRule toExchangeSectionRule(
映射接口代码
@Mapper( componentModel = "spring", collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED, nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS) public interface ProfileMapper { @Named("sectionTargetingRule") @Mapping(source="version", target = "version") @Mapping(source="items", target = "items") // @Mapping(target = "items", ignore = true) SectionTargetingRule toExchangeSectionRule( com.jmoncayo.types.SectionTargetingRule sectionTargetingRule); @Mapping(source = "include", target = "include") @Mapping(source = "exclude", target = "exclude") SectionTargetingGroupIncludeExclude toExchangeSectionTargetIncludeExclude( com.jmoncayo.types.SectionTargetingGroupIncludeExclude sectionTargetingRule); List<SectionTargetingGroup> toExchangeSectionTargetingGroups(List<com.jmoncayo.types.SectionTargetingGroup> sectionTargetingGroups); @Mapping(source = "name", target="name") @Mapping(source = "items", target="items") SectionTargetingGroup toExchangeSectionTarget( com.jmoncayo.types.SectionTargetingGroup sectionTargetingGroup); }
问题原因与解决方案
核心原因
目标类SectionTargetingRule继承了TargetingRule,父类TargetingRule中存在一个名为items的字段,类型为List<TargetingTuple>。MapStruct在解析目标类字段时,混淆了父类的items字段与子类自定义的SectionTargetingGroupIncludeExclude类型的items字段,因此尝试将源对象的SectionTargetingGroupIncludeExclude类型items转换为父类的List<TargetingTuple>类型,导致类型不匹配错误。
解决方案
明确指定字段映射规则:在
@Mapping注解中通过qualifiedByName指定对应的转换方法,确保MapStruct使用你定义的SectionTargetingGroupIncludeExclude转换逻辑:@Named("sectionTargetingRule") @Mapping(source="version", target = "version") @Mapping(source="items", target = "items", qualifiedByName = "toExchangeSectionTargetIncludeExclude") SectionTargetingRule toExchangeSectionRule( com.jmoncayo.types.SectionTargetingRule sectionTargetingRule);忽略父类冲突字段:如果父类的
items字段并非业务所需,可显式忽略父类的items字段,避免MapStruct混淆:@Named("sectionTargetingRule") @Mapping(source="version", target = "version") @Mapping(source="items", target = "items") @Mapping(target = "super.items", ignore = true) // 忽略父类的items字段 SectionTargetingRule toExchangeSectionRule( com.jmoncayo.types.SectionTargetingRule sectionTargetingRule);注:部分MapStruct版本支持
super.前缀指定父类字段,若不支持,可调整类结构或修改父类字段名规避冲突。确认类导入正确性:检查映射接口中导入的
SectionTargetingRule是否为目标类(继承TargetingRule的版本),避免类名混淆导致字段解析错误。
内容的提问来源于stack exchange,提问作者andresmonc

