如果MapStruct在将A类型转换为B类型时,匹配到多个映射方法【这些映射方法的入参都是A类型,返回值是B类型】。则程序会报编译错误,MapStruct会给出相应的提示。 我们先来看个具体的例子。 实体类型定义如下:@Data public class OriginalRelease { private String title; } @Data public class GermanRelease { private String title; } 我们有个工具类支持将title转换成德语和英语。public class Titles { /** * 将title 转换为 德语 * * @param title * @return */ public String transTitle2German(String title) { return "German: " + title; } /** * 将title 转换为 英语 * * @param title * @return */ public String transTitle2English(String title) { return "English: " + title; } } Mapper类定义如下:@Mapper(uses = Titles.class) public interface ReleaseMapper { GermanRelease toGerman(OriginalRelease release); } 上述代码编译后,会报如下错误: Ambiguous mapping methods found for mapping property "String title" to String: String Titles.transTitle2German(String title), String Titles.transTitle2English(String title). See https://mapstruct.org/faq/#ambiguous for more info. 大概意思就是:MapStruct在将OriginalRelease.title转换为GermanRelease.title时。匹配到2个方法,分别是:String Titles.transTitle2German(String title) 和 String Titles.transTitle2English(String title)。 MapStruct无法决定使用哪个方法进行转换,因此报错。 针对上面的场景,MapStruct提供了qualifiers机制 ,供程序员明确指定使用哪个方法进行转换。 qualifiers机制提供了两种方式:qualifiedBy 和 qualifiedByName。下面我们分别来介绍这两种用法。 1、qualifiedBy (1)首先我们需要定义注解,该注解用于标识我们的转换方法(Mapping Method);@Qualifier @Target(ElementType.METHOD) @Retention(RetentionPolicy.CLASS) public @interface ToGerman { } @Qualifier @Target(ElementType.METHOD) @Retention(RetentionPolicy.CLASS) public @interface ToEnglish { }关于定义的注解,这里说三点: (1)该注解必须使用@Qualifier标注; (2)该注解只能作用于方法; (3)该注解RetentionPolicy为RetentionPolicy.CLASS (2)使用定义的注解 标注转换方法(Mapping Method); 如此一来,注解和转换方法就建立了对应关系。public class Titles { @ToGerman public String transTitle2German(String title) { return "German: " + title; } @ToEnglish public String transTitle2English(String title) { return "English: " + title; } } (3)在Mapper中使用注解,指定转换方法。 为@Mapping#qualifiedBy指定对应的注解,用于表示使用其标注的转换方法进行转换。@Mapper(uses = Titles.class) public interface ReleaseMapper { ReleaseMapper INSTANCE = Mappers.getMapper(ReleaseMapper.class); @Mapping(target = "title", qualifiedBy = ToGerman.class) GermanRelease toGerman(OriginalRelease release); @Mapping(target = "title", qualifiedBy = ToEnglish.class) EnglishRelease toEnglish(OriginalRelease release); } 注意:这里的uses = Titles.class是必须加上的,否则MapStruct会报找不到对应注解标注的转换方法。 (4)生成的Mapper实现类的代码public class ReleaseMapperImpl implements ReleaseMapper { private final Titles titles = new Titles(); @Override public GermanRelease toGerman(OriginalRelease release) { if ( release == null ) { return null; } GermanRelease germanRelease = new GermanRelease(); germanRelease.setTitle( titles.transTitle2German( release.getTitle() ) ); return germanRelease; } @Override public EnglishRelease toEnglish(OriginalRelease release) { if ( release == null ) { return null; } EnglishRelease englishRelease = new EnglishRelease(); englishRelease.setTitle( titles.transTitle2English( release.getTitle() ) ); return englishRelease; } } 2、qualifiedByName (1)使用@Named注解为转换方法设置别名。public class Titles { @Named("toGerman") public String transTitle2German(String title) { return "German: " + title; } @Named("toEnglish") public String transTitle2English(String title) { return "English: " + title; } } (2)在Mapper中使用别名,指定转换方法。 为@Mapping#qualifiedBy指定对应的别名,用于表示使用其标注的转换方法进行转换。@Mapper(uses = Titles.class) public interface ReleaseMapper { ReleaseMapper INSTANCE = Mappers.getMapper(ReleaseMapper.class); @Mapping(target = "title", qualifiedByName = "toGerman") GermanRelease toGerman(OriginalRelease release); @Mapping(target = "title", qualifiedByName = "toEnglish") EnglishRelease toEnglish(OriginalRelease release); } 注意:这里的uses = Titles.class是必须加上的,否则MapStruct会报找不到对应别名标注的转换方法。