我正在使用mapstruct从一个DTO映射到另一个。我有多个默认方法,但其中两个方法的返回值为String,并且使用与输入参数相同的类,这给了我"使用java Mapstruct的模糊映射方法"错误。我在这里添加代码的相关部分:
@Mappings({
@Mapping(source = "programInstance", target = "title", qualifiedByName = "title"),
@Mapping(source = "programInstance", target = "seriesName", qualifiedByName = "seriesName"),
@Mapping(source = "programInstance", target = "season", qualifiedByName = "season"),
@Mapping(source = "programInstance", target = "epNumber", qualifiedByName = "epNumber"),
})
DTO1 mapDTOs (DTO2 dto2);
@Named("title")
default String mapTitle(Program programInstance) {
Optional<String> title = Utils.getObject(() -> programInstance.getTitle().getDescriptions().get(0).getValue());
if (title.isPresent())
return title.get();
return null;
}
@Named("seriesName")
default String mapSeriesName(Program programInstance) {
Optional<String> seriesName = Utils.getObject(() -> programInstance.get(0).getProgram().getTitle().getDescriptions().get(0).getValue());
if (seriesName.isPresent())
return seriesName.get();
return null;
}
@Named("season")
default Integer mapSeasonNumber(Program programInstance) {
Optional<Integer> season = Utils.getObject(() -> programInstance.get(0).getSeasonOf().get(0).getOrderNo());
if (season.isPresent())
return season.get();
return null;
}
@Named("epNumber")
default Integer mapEpNumber(Program programInstance) {
Optional<Integer> epNumber = Utils.getObject(() -> programInstance.getEpOf().get(0).getOrderNo());
if (epNumber.isPresent())
return epNumber.get();
return null;
}
错误为
为映射属性"程序"找到不明确的映射方法programInstance"转换为java.lang.String:java.lang.Sstring mapTitle(),java.lang.String mapSeriesName()。
我检查了您的示例。。问题是,您尝试针对的字段的类型是String。
因此:
public class IvpVodOfferStatusDTO {
private String seasonNumber;
private String episodeNumber;
}
MapStruct试图将其与您提供的签名相匹配:
@Named("season")
default Integer mapSeasonNumber(Program programInstance) {
Optional<Integer> season = Utils.getObject(() -> programInstance.get(0).getSeasonOf().get(0).getOrderNo());
if (season.isPresent())
return season.get();
return null;
}
@Named("epNumber")
default Integer mapEpNumber(Program programInstance) {
Optional<Integer> epNumber = Utils.getObject(() -> programInstance.getEpOf().get(0).getOrderNo());
if (epNumber.isPresent())
return epNumber.get();
return null;
}
MapStruct有一个预定义的尝试顺序:
- 用户提供的映射方法
- Direct(源-目标类型相同)
- 映射方法(内置)
- 类型转换
如果这一切都失败了,MapStruct会尝试采取两步方法:
- 映射方法-映射方法
- 映射方法-类型转换
- 类型转换映射方法
在6。它找到2个限定方法(Program
到String
)。MapStruct中可能有一个错误,即它选择了@Named
不合格的方法(需要检查这是否是故意的)。否则,我会写一期。
最简单的解决方案是:调整目标:
public class IvpVodOfferStatusDTO {
private Integer seasonNumber;
private Integer episodeNumber;
}
你的意图可能是什么(我想)。。否则,您可以更改签名,不返回Integer
,而是返回String
即使数据类型匹配,如果在qualifiedByName中给定的名称没有定义为bean实例,也可能发生这种情况
因为如果没有匹配的@Named限定符,注入器将不知道要绑定到哪个变量的bean
@Mapping( source = "firstName", target = "passenger.firstName", qualifiedByName = "mapFirstName" )
public abstract Passenger mapPassenger( Traveller traveller );
@Named( "mapFirstName" )
String mapFirstName( String firstName)
{
}
我遇到了同样的问题,并观察到,我的映射器类使用@mapper(uses={BaseMapper.class})和使用extends BaseMapper继承了同样的方法。删除扩展为我解决了问题。所以,您可以通过多种方式查找自定义映射器接收的方法。
另外请注意,如果您有循环依赖项,则可能会得到此项:
ObjectA -> ObjectB -> ObjectA -> ObjectB
在大多数情况下,它将被报告为一个不明确的条目。解决方案是在ObjectB中不引用对象A。
@Named("name")
方法注释与相同的"name"
重复,也可能发生Ambiguous mapping methods
:它们需要在@Named
方法中是唯一的。