英文:
How to use qualifiedByName with subclass mapping
问题
You can achieve this by specifying the qualifiedByName
attribute in the @BeanMapping
annotation for the toMatchApiMissing
method in your DetailsApiMapper
. Here's how you can modify the DetailsApiMapper
:
@Mapper(uses = {
LolDetailsApiMapper.class,
CsgoDetailsApiMapper.class,
DotaDetailsApiMapper.class
})
public interface DetailsApiMapper {
@BeanMapping(unmappedTargetPolicy = IGNORE, qualifiedByName = "toMatchApiMissing")
@SubclassMapping(target = Match.class, source = LolMatchDetails.class)
@SubclassMapping(target = Match.class, source = CsgoMatchDetails.class)
@SubclassMapping(target = Match.class, source = DotaMatchDetails.class)
Match toApi(MatchDetails matchDetails);
@BeanMapping(unmappedTargetPolicy = IGNORE, qualifiedByName = "toMatchApiMissing")
@SubclassMapping(target = Match.class, source = LolMatchDetails.class)
@SubclassMapping(target = Match.class, source = CsgoMatchDetails.class)
@SubclassMapping(target = Match.class, source = DotaMatchDetails.class)
Match toMatchApiMissing(MatchDetails matchDetails);
}
By specifying qualifiedByName = "toMatchApiMissing"
in both @BeanMapping
annotations for the toMatchApiMissing
method, you're telling MapStruct to use the toMatchApiMissing
method in the specific mappers (e.g., LolDetailsApiMapper
, CsgoDetailsApiMapper
, or DotaDetailsApiMapper
) that have this method with the same qualified name. This should make DetailsApiMapper.toMatchApiMissing
use the toMatchApiMissing
of the other mappers correctly.
英文:
I have the following mappers:
@Mapper(uses = ApiMapper.class,
// Disable use of the builders which we mostly need for testing.
builder = @Builder(disableBuilder = true))
public interface CsgoDetailsApiMapper {
@Mapping(target = "title", source = "match.title")
@Mapping(target = "status", source = "match.state")
@Mapping(target = "teams", source = "match.teams")
@Mapping(target = "games", source = "gameDetails")
@Mapping(target = "id", source = "match.id")
@Mapping(target = "facts", source = "matchDetails")
Match toApi(CsgoMatchDetails matchDetails);
@Named("toMatchApiMissing")
@Mapping(target = "title", source = "match.title")
@Mapping(target = "status", source = "match.state")
@Mapping(target = "teams", source = "match.teams")
@Mapping(target = "games", source = "gameDetails", qualifiedByName = "toGameApiMissing")
@Mapping(target = "id", source = "match.id")
@Mapping(target = "facts", source = "matchDetails")
Match toMatchApiMissing(CsgoMatchDetails matchDetails);
...
}
Similar to this I have two more mappers looking exactly the same. LolDetailsApiMapper
and DotaDetailsApiMapper
then I have a details mapper that should use the implementation of the specific mappers:
@Mapper(uses = {
LolDetailsApiMapper.class,
CsgoDetailsApiMapper.class,
DotaDetailsApiMapper.class
})
public interface DetailsApiMapper {
@BeanMapping(unmappedTargetPolicy = IGNORE)
@SubclassMapping(target = Match.class, source = LolMatchDetails.class)
@SubclassMapping(target = Match.class, source = CsgoMatchDetails.class)
@SubclassMapping(target = Match.class, source = DotaMatchDetails.class)
Match toApi(MatchDetails matchDetails);
@BeanMapping(unmappedTargetPolicy = IGNORE)
@SubclassMapping(target = Match.class, source = LolMatchDetails.class)
@SubclassMapping(target = Match.class, source = CsgoMatchDetails.class)
@SubclassMapping(target = Match.class, source = DotaMatchDetails.class)
Match toMatchApiMissing(MatchDetails matchDetails);
}
How can I make the DetailsApiMapper.toMatchApiMissing
use the toMatchApiMissing
of the other mappers, instead of the toApi
? I tried adding @Named("toMatchApiMissing")
to the specific mappers and then tried to use @BeanMapping(unmappedTargetPolicy = IGNORE, qualifiedByName="toMatchApiMissing")
, but this didn't work. Is this possible? Thanks in advance.
答案1
得分: 0
尝试在所有子类映射器的toApi
方法上使用@Named
进行注解,而不是使用toMatchApiMissing
方法,如下所示:
@Mapper(uses = ApiMapper.class,
// Disable use of the builders which we mostly need for testing.
builder = @Builder(disableBuilder = true))
public interface CsgoDetailsApiMapper {
@Named("toApi")
@Mapping(target = "title", source = "match.title")
@Mapping(target = "status", source = "match.state")
@Mapping(target = "teams", source = "match.teams")
@Mapping(target = "games", source = "gameDetails")
@Mapping(target = "id", source = "match.id")
@Mapping(target = "facts", source = "matchDetails")
Match toApi(CsgoMatchDetails matchDetails);
@Mapping(target = "title", source = "match.title")
@Mapping(target = "status", source = "match.state")
@Mapping(target = "teams", source = "match.teams")
@Mapping(target = "games", source = "gameDetails", qualifiedByName = "toGameApiMissing")
@Mapping(target = "id", source = "match.id")
@Mapping(target = "facts", source = "matchDetails")
Match toMatchApiMissing(CsgoMatchDetails matchDetails);
}
然后重新构建项目并检查生成的映射器实现。这是一个奇怪的解决方案,但在我的情况下,Mapstruct选择了正确的映射方法,即那些没有使用@Named
进行注解的方法。
编辑:
我找到了与该主题相关的问题,似乎即将发布的1.6.0
里程碑版本将允许在SubclassMapping
注解中使用限定符。
发布后,您将能够定义子类映射如下:
@SubclassMapping(target = Match.class, source = CsgoMatchDetails.class, qualifiedByName = "toMatchApiMissing")
英文:
Try to annotate toApi
method in all subclass mappers with @Named
, instead of toMatchApiMissing
method, as shown below:
@Mapper(uses = ApiMapper.class,
// Disable use of the builders which we mostly need for testing.
builder = @Builder(disableBuilder = true))
public interface CsgoDetailsApiMapper {
@Named("toApi")
@Mapping(target = "title", source = "match.title")
@Mapping(target = "status", source = "match.state")
@Mapping(target = "teams", source = "match.teams")
@Mapping(target = "games", source = "gameDetails")
@Mapping(target = "id", source = "match.id")
@Mapping(target = "facts", source = "matchDetails")
Match toApi(CsgoMatchDetails matchDetails);
@Mapping(target = "title", source = "match.title")
@Mapping(target = "status", source = "match.state")
@Mapping(target = "teams", source = "match.teams")
@Mapping(target = "games", source = "gameDetails", qualifiedByName = "toGameApiMissing")
@Mapping(target = "id", source = "match.id")
@Mapping(target = "facts", source = "matchDetails")
Match toMatchApiMissing(CsgoMatchDetails matchDetails);
}
Then rebuild the project and check the generated mapper implementation. It's a weird solution, but in my case, Mapstruct picked the right methods for mapping, i.e. those not annotated with @Named
.
EDIT:
I've found the issue related to the topic, and it appears that the upcoming 1.6.0
milestone release will enable the use of qualifiers within the SubclassMapping
annotation.
After the release, you will be able to define a subclass mapping as follows:
@SubclassMapping(target = Match.class, source = CsgoMatchDetails.class, qualifiedByName = "toMatchApiMissing")
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论