Mapstruct 集合映射 从相同的源类映射扩展类异常问题—— Ambiguous mapping methods found for mapping collection element
问题1:
票证实体
public class Ticket {
private long id;
private String title;
private Set<Comment> comments;
// Getters and setters
}
票证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
}
票务映射器界面
@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
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).
最佳答案
这是一个简单的修复,确实是缺少的配置问题。缺少的是@IterableMapping
批注。
@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);
}
========================
问题2: 多集合Mapping异常 BaseDO 为父类
/**
* dtoToDO
*
* @param dto
* @return
*/
ObjectControlDO dtoToDO(ObjectControlDto dto);
/**
* dtosToDOs
*
* @param dtos
* @return
*/
List<ObjectControlDO> dtosToDOs(List<ObjectControlDto> dtos);
/**
* dtoToDO
*
* @param dto
* @return
*/
BaseDO dtoToBaseDO(ObjectControlDto dto);
/**
* dtosToDOs
*
* @param dtos
* @return
*/
List<BaseDO> dtosToBaseDOs(List<ObjectControlDto> dtos);
解决方式
/**
* dtoToDO
*
* @param dto
* @return
*/
@Named(value = "dtoToDO")
ObjectControlDO dtoToDO(ObjectControlDto dto);
/**
* dtosToDOs
*
* @param dtos
* @return
*/
@IterableMapping(qualifiedByName = "dtoToDO")
List<ObjectControlDO> dtosToDOs(List<ObjectControlDto> dtos);
/**
* dtoToDO
*
* @param dto
* @return
*/
@Named(value = "dtoToBaseDO")
BaseDO dtoToBaseDO(ObjectControlDto dto);
/**
* dtosToDOs
*
* @param dtos
* @return
*/
@IterableMapping(qualifiedByName = "dtoToBaseDO")
List<BaseDO> dtosToBaseDOs(List<ObjectControlDto> dtos);
3、 mapstruct-将父字段值传播给嵌套对象的集合
可以将值从父对象传播到嵌套对象的集合
DTO源类
class CarDTO {
private String name;
private long userId;
private Set<WheelDto> wheels;
};
class WheelDto {
private String name;
}
目标实体类
class Car {
private String name;
private long userId;
private Set<Wheel> wheels;
};
class Wheel {
private String name;
private long lastUserId;
}
如您所见,我在WheelDto上没有lastUserId,因此我想在wheel集合中的每个对象上将CarDto的userId映射到WheelDto的lastUserId。
最佳答案
当前无法传递属性。但是,您可以通过@AfterMapping
和/或@Context
解决此问题。
汽车映射后更新车轮
但是,这意味着您需要对Wheel
进行两次迭代。它看起来像
@Mapper
public interface CarMapper {
Car map(CarDto carDto);
@AfterMapping
default void afterCarMapping(@MappingTarget Car car, CarDto carDto) {
car.getWheels().forEach(wheel -> wheel.setLastUserId(carDto.getUserId()));
}
}
在映射轮时传递@Context以便在映射期间具有状态
如果您只想通过Wheel
进行一次迭代,则可以传递一个@Context
对象,该对象将在映射汽车之前从CarDto
获取userId,然后在之后的映射中将其设置在Wheel
上。该映射器如下所示:
@Mapper
public interface CarMapper {
Car map(CarDto carDto, @Context CarContext context);
Wheel map(WheelDto wheelDto, @Context CarContext context);
}
public class CarContext {
private String lastUserId;
@BeforeMapping
public void beforeCarMapping(CarDto carDto) {
this.lastUserId = carDto.getUserId();
}
@AfterMapping
public void afterWheelMapping(@MappingTarget Wheel wheel) {
wheel.setLastUserId(lastUserId);
}
}
CarContext
将传递到车轮映射方法。
Mapstruct-从多个集合映射到单个集合
使用MapStruct,我的源对象中有两个集合,其中包含略有不同的对象。我想将这两个集合的对象映射为通用类型,然后将它们全部插入单个集合中。类似于以下内容:
List<UserNumber> listsToDtoList(List<PhoneNumber> phoneNumbers, List<FaxNumber> faxNumbers);
UserNumber phoneToPhoneDto(PhoneNumber phone);
UserNumber faxToPhoneDto(FaxNumber fax);
使用MapStruct做到这一点的最简单方法是什么?
最佳答案
因此,我将根据我的SourceObject
进行映射(不写List<UserNumber> listsToDtoList(List<PhoneNumber> phoneNumbers, List<FaxNumber> faxNumbers);
所以大致如下:
@Mapping( target = "userNumbers", source = "phoneNumbers" )
Target map( Source source );
@AfterMapping // will be applied in the final part of the previous method
default void map ( Source source, @MappingTarget Target target ) {
target.getUserNumbers().addAll(source.getFaxNumbers());
}
参照:
下一篇: MVVM WPF 绑定颜色