我需要使用 MapStruct 将一些实体和实体列表转换为单个 DTO。此 DTO 包含嵌套列表。
比方说,我有以下持久化支持的 POJO:
public class Entity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@Column(name = "name", nullable = false)
private String name;
// SKIPPED
@OneToOne(mappedBy = "entity", cascade = CascadeType.ALL)
private EntityMetadata entityMetadata;
}
以及该实体的一些集合:
List<Entity> entities
DTO 介绍如下:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class ScreenDocumentDto { // dto
private Long id;
private String name;
List<SomeLinkDto> someLinks;
}
以及嵌套的DTO:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class SomeLinkDto {
private Long id;
private ZonedDateTime someDate;
}
除了 someLinks 列表之外的所有字段我需要从实体映射:
dto.setId(entity.getId());
dto.setName(entity.getName());
// SKIPPED
我填充的嵌套列表如下:
List<SomeLinkDto> someLinks = new ArrayList<>(entities.size());
for (Entity entity : entities) {
someLinks.add(SomeLinkDto.builder().id(entity.getId())
.someDate(entity.getEntityMetadata().getSomeDate()).build());
}
结果涉及大量手动转换:
@Mapper(componentModel = "spring")
public interface ScreenDocumentMapper extends BaseMapper<Entity, ScreenDocumentDto> {
default ScreenDocumentDto toScreenDocumentDto(List<Entity> entities, Entity entity) {
ScreenDocumentDto dto = new ScreenDocumentDto();
List<SomeLinkDto> someLinks = new ArrayList<>(entities.size());
for (Entity entity : entities) {
someLinks.add(SomeLinkDto.builder().id(entity.getId())
.someDate(entity.getEntityMetadata().getSomeDate()).build());
}
dto.setId(entity.getId());
dto.setName(entity.getName());
...
dto.setSomeLinks(someLinks);
return dto;
}
// SKIPPED
有没有办法使用 MapStruct 的功能来完成相同的工作?像这样:
@Mapper(componentModel = "spring")
public interface ScreenDocumentMapper extends BaseMapper<Entity, ScreenDocumentDto> {
@Mappings({
@Mapping(source = "...", target = "..."),
...
})
ScreenDocumentDto toDto(Entity entity);
}
您可以通过使用多个源参数,通过 MapStruct 实现自定义
toScreenDocumentDto
方法。
例如
@Mapper(componentModel = "spring")
public interface ScreenDocumentMapper extends BaseMapper<Entity, ScreenDocumentDto> {
@Mapping(source = "entities", target = "someLinks")
ScreenDocumentDto toDto(Entity entity, List<Entity> entities);
@Mapping(source = "entityMetadata.someDate", target = "someDate")
SomeLinkDto toLinkDto(Entity entity);
}
如果
Entity
具有链接作为属性,您可以执行以下操作:
@Mapper(componentModel = "spring")
public interface ScreenDocumentMapper extends BaseMapper<Entity, ScreenDocumentDto> {
@Mapping(source = "links", target = "someLinks")
ScreenDocumentDto toDto(Entity entity);
@Mapping(source = "entityMetadata.someDate", target = "someDate")
SomeLinkDto toLinkDto(Entity entity);
}
在您的映射方法下添加以下注释。
@Mapping(target = "someLinks",expression = "java(Arrays.asList(new SomeLinkDTO(id,someDate)))"
并在映射器界面之上添加注释。
@Mapper(imports = {Arrays.class ,SomeLinkDTO.class})
@Mapper
public interface SomeLinkMapper{
SomeLinkDTO toDto(SomeLink someLink);
List<SomeLinkDTO> toListDto(List<SomeLink> someLinks);
}
@Mapper(collectionMappingStrategy = CollectionMappingStrategy.ADDER_PREFERRED,
uses = SomeLinkMapper.class)
public interface ScreenDocumentMapper {
ScreenDocumentDTO toDto(ScreenDocument screenDocument);
}