我已经开始使用Mapstruct将JPA实体映射到DTO&#39。对于基本实体,这很有用。
我的问题:某些实体拥有延迟加载的集合,其中包含我不想总是想要获取和映射的其他详细信息。作为一种解决方案,我添加了一个基本的超类,其中包含所有始终映射的字段,以及包含集合的子类。它们都代表相同的实体,因此它们使用相同的源类。
当我尝试创建一个包含映射到同一源的两种类型的方法的Mapper时,即使方法签名(至少返回类型)不同,我也会得到一个模糊的映射方法错误。 我是以错误的方式来做这件事的吗?我不能使用同一来源为DTO使用子类吗?
修改 如果重要,我使用的是mapstruct-jdk8:1.1.0.Final
编辑2: 下面的例子只是一个例子,在我的头顶。当我实际使用该代码时,它起作用了。事实证明我的问题是在示例中没有包含的内容。当我添加一个映射票证集合的方法时,似乎发生了错误。这可能意味着问题不是(直接?)与继承相关。我可能错过了一些配置,但我不确定该寻找什么。
简单示例:
故障单实体
public class Ticket {
private long id;
private String title;
private Set<Comment> comments;
// Getters and setters
}
Ticket DTO
public class TicketDTO {
private long id;
private String title;
// Getters and setters
}
带有评论的票证DTO
public class TicketWithCommentsDTO extends TicketDTO {
private List<CommentDTO> comments;
// Getters and setters
}
Ticket Mapper界面
@Mapper(uses= { CommentMapper.class })
public interface TicketMapper {
TicketDTO mapToTicketDTO(Ticket ticket);
List<TicketDTO> mapToTicketDTOList(Collection<Ticket> tickets); // Adding this method or the last method causes the error
TicketWithCommentsDTO mapToTicketWithCommentsDTO(Ticket ticket);
List<TicketWithCommentsDTO> MapToTicketWithCommentDTOList(Collection<Ticket> tickets);
}
评论Mapper界面
@Mapper
public interface CommentMapper {
CommentDTO toCommentDTO(Comment comment);
List<CommentDTO> toCommentDTOList(Collection<Comment> comments);
}
抛出的错误:
Ambiguous mapping methods found for mapping collection element to
dto.TicketDTO: dto.TicketDTO mapToTicketDTO(model.Ticket ticket),
dto.TicketWithCommentsDTO mapToTicketWithCommentsDTO(model.Ticket ticket).
答案 0 :(得分:2)
嗯,原来这是一个简单的修复,它确实是一个缺少的配置问题。缺少的是@IterableMapping
注释。
一旦我将elementTargetType
设置为正确的类型,一切都按预期工作。
正确的Mapper代码
@Mapper(uses = { CommentMapper.class })
public interface TicketMapper {
TicketDTO mapToTicketDTO(Ticket ticket);
@IterableMapping(elementTargetType = TicketDTO.class)
List<TicketDTO> mapToTicketDTOList(Collection<Ticket> tickets);
TicketWithCommentsDTO mapToTicketWithCommentsDTO(Ticket ticket);
@IterableMapping(elementTargetType = TicketWithCommentsDTO.class)
List<TicketWithCommentsDTO> mapToTicketWithCommentDTOList(Collection<Ticket> tickets);
}
答案 1 :(得分:0)
您可以通过添加如下所示的映射方法来进行子类映射:
@Mapper(...)
public interface SuperClassMapper {
SubClassMapper SUBCLASS_MAPPER_INSTANCE = Mappers.getMapper(SubClassMapper.class);
// Mappings entity to dto / dto to entity ...
@AfterMapping
default SuperClassDTO toSubClassDTO(SuperClass entity, @MappingTarget SuperClassDTO dto)
{
if (entity instanceof SubClass) {
return SUBCLASS_MAPPER_INSTANCE.toDto((SubClass) entity);
}
return dto;
}
您当然应该已经定义了SubClassMapper。