Mapstruct-为映射属性找到不明确的映射方法



我正在使用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有一个预定义的尝试顺序:

  1. 用户提供的映射方法
  2. Direct(源-目标类型相同)
  3. 映射方法(内置)
  4. 类型转换

如果这一切都失败了,MapStruct会尝试采取两步方法:

  1. 映射方法-映射方法
  2. 映射方法-类型转换
  3. 类型转换映射方法

在6。它找到2个限定方法(ProgramString)。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方法中是唯一的。

最新更新