如果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)首先我们需要定义注解,该注解用于标识我们的转换方法(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;
}
}
(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会报找不到对应别名标注的转换方法。
页面更新:2024-04-25
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号