如何使用MapStruct将实体和实体列表映射到具有嵌套列表的单个DTO?

问题描述 投票:0回答:3

我需要使用 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);
}
java mapstruct
3个回答
1
投票

您可以通过使用多个源参数,通过 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);
}

0
投票

在您的映射方法下添加以下注释。

@Mapping(target = "someLinks",expression = "java(Arrays.asList(new SomeLinkDTO(id,someDate)))"

并在映射器界面之上添加注释。

@Mapper(imports = {Arrays.class ,SomeLinkDTO.class})

0
投票
@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);
}
© www.soinside.com 2019 - 2024. All rights reserved.