如何将Page<ObjectEntity>映射到spring-data-rest中的Page<ObjectDTO>

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

当我使用

PagingAndSortingRepository.findAll(Pageable)
访问数据库时,我得到
Page<ObjectEntity>
。但是,我想向客户端而不是实体公开 DTO。我可以通过将实体注入到 DTO 的构造函数中来创建 DTO,但是如何将 Page 对象中的实体映射到 DTO 呢?根据spring文档,Page提供只读操作。

此外,Page.map 也是不可能的,因为我们不支持 java 8。如何手动创建带有映射对象的新页面?

java spring spring-mvc spring-data spring-data-rest
14个回答
98
投票

您仍然可以使用

Page.map
而不使用 lambda 表达式:

Page<ObjectEntity> entities = objectEntityRepository.findAll(pageable);
Page<ObjectDto> dtoPage = entities.map(new Converter<ObjectEntity, ObjectDto>() {
    @Override
    public ObjectDto convert(ObjectEntity entity) {
        ObjectDto dto = new ObjectDto();
        // Conversion logic

        return dto;
    }
});

32
投票

在 Spring Data 2 中,Page map 方法采用 Function 而不是 Converter,但它的工作原理仍然与@Ali Dehghani 描述的基本相同。

使用功能:

Page<ObjectEntity> entities = objectEntityRepository.findAll(pageable);
Page<ObjectDto> dtoPage = entities.map(new Function<ObjectEntity, ObjectDto>() {
    @Override
    public ObjectDto apply(ObjectEntity entity) {
        ObjectDto dto = new ObjectDto();
        // Conversion logic

        return dto;
    }
});

31
投票

在java8中:

Page<ObjectDto> entities = 
 objectEntityRepository.findAll(pageable)
 .map(ObjectDto::fromEntity);

其中 fromEntity 是 ObjectDto 上的静态方法,包含转换逻辑。


12
投票

您可以通过简单地执行以下操作来使用Page.map:

public Page<ObjectDto> toPageObjectDto(Page<Object> objects) {
    Page<ObjectDto> dtos  = objects.map(this::convertToObjectDto);
    return dtos;
}

private ObjectDto convertToObjectDto(Object o) {
    ObjectDto dto = new ObjectDto();
    //conversion here
    return dto;
}

6
投票

我创建了一个包含模型映射器、泛型和 lambda 的通用解决方案,并且每天都会在多个项目中使用它。

/**
 * Maps the Page {@code entities} of <code>T</code> type which have to be mapped as input to {@code dtoClass} Page
 * of mapped object with <code>D</code> type.
 *
 * @param <D> - type of objects in result page
 * @param <T> - type of entity in <code>entityPage</code>
 * @param entities - page of entities that needs to be mapped
 * @param dtoClass - class of result page element
 * @return page - mapped page with objects of type <code>D</code>.
 * @NB <code>dtoClass</code> must has NoArgsConstructor!
 */
public <D, T> Page<D> mapEntityPageIntoDtoPage(Page<T> entities, Class<D> dtoClass) {
    return entities.map(objectEntity -> modelMapper.map(objectEntity, dtoClass));
} 

这正是您需要的情况(我认为这是其他各种情况的常见情况)。

您已经通过这种方式从存储库获取了数据(与服务相同):

Page<ObjectEntity> entities = objectEntityRepository.findAll(pageable);

转换所需的一切就是以这种方式调用此方法:

Page<ObjectDto> dtoPage = mapEntityPageIntoDtoPage(entities, ObjectDto.class);

@Tip:您可以在 util 类中使用此方法,并且根据您的架构,它可以重用于服务和控制器上的页面转换中的所有实体/dto。

示例:

Page<ObjectDto> dtoPage = mapperUtil.mapEntityPageIntoDtoPage(entities, ObjectDto.class);

4
投票

这是我的解决方案,感谢@Ali Dehghani

private Page<ObjectDTO> mapEntityPageIntoDTOPage(Page<ObjectEntity> objectEntityPage) {
        return objectEntityPage.map(new Converter<ObjectEntity, ObjectDTO>() {
            public ObjectDTO convert(ObjectEntity objectEntity) {
                return new ObjectDTO(objectEntity, httpSession);
            }

        });
    }

3
投票

使用lambda表达式更方便

Page<ObjectDto> dto=objectRepository.findAll(pageable).map((object -> DozerBeanMapperBuilder.buildDefault().map(object, ObjectDto.class)));

3
投票
Page<Order> persistedOrderPage = orderQueryRepository.search();

Page<OrderDTO> orderPage = persistedOrderPage.map(persistedOrder -> {
    OrderDTO order = mapper.toOrderDTO(persistedOrder);
    // do another action
    return order;
});

2
投票

这在 Spring 2.0 中可以正常工作 -

@Override
public Page<BookDto> getBooksByAuthor(String authorId, Pageable pageable) {
        Page<BookEntity> bookEntity = iBookRepository.findByAuthorId(authorId, pageable);
        return bookEntity.map(new Function<BookEntity, BookDto>() {

            @Override
            public BookDto apply(BookEntity t) {
                return new ModelMapper().map(t, BookDto.class);
            }

        });
    }

Spring 2.0 的页面类型不再支持该转换器。另外,函数应该从 java.util.function.Function 中使用。


2
投票

使用 Java 8 Lambda,它对我有用。上面已经给出了答案,我只是简化一下。

Page<EmployeeEntity> employeeEntityPage = employeeService.findEmployeeEntities();


Page<EmployeeDto> employeeDtoPage = employeeEntityPage.map(entity -> {
        EmployeeDto dto = employeeService.employeEntityToDto(entity);
        return dto;
    });

这里的employeeEntityToDto()是一个将Entities转换为Dtos的方法

public EmployeeDto employeeEntityToDto(EmployeeEntity entity){
    EmployeeDto employeeDto =  new EmployeeDto();
    employeeDto.setId(entity.getId());
    employeeDto.setName(entity.getName());
    return employeeDto;
}

2
投票

我将 Lambda 与 ModelMapper

结合使用
    Page<ObjectEntity> pageEntity = objectRepository.findAll(pageable);
    Page<ObjectDto> pageDto = pageEntity.map(objectEntity -> modelMapper.map(objectEntity, ObjectDto.class));

0
投票

最后,您不会将页面返回给用户,而是返回一个 ObjectDTO 列表,页面详细信息位于标题处,所以这将是我的解决方案。

对象服务

public Page<ObjectEntity> findAll (Pageable pageable){
  //logic goes here.
  Page<ObjectEntity> page = objectRepository.findAll(pageable);
  return page;
} 

ObjectResource/rest(暴露的端点)

@GetMapping
public ResponseEntity<List<ObjectDTO>> findAll (Pageable pageable){
  Page<ObjectEntity> page = objectServiceService.findAll(pageable);

  HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "your-endpoint-here");

  return new ResponseEntity<>(objectMapper.toDto(page.getContent()), headers, HttpStatus.OK);
}

使用这个的原因是这样你就不需要复制ObjectEntity和DTO的页面详细信息。需要注意的是,页面包含以下内容:

  • 页码
  • 页面大小
  • 元素数量
  • 内容

content是返回的对象列表,并且是唯一需要映射到DTO的东西。


0
投票

试试这个代码

服务

Pageable pageable = PageRequest.of(page - 1, size);
Page<ContentResDTO> resDTOPage = contentRepository.findAllBy(contentID, userId, pageable);

存储库

@Query("SELECT new com.example.demo.dto.content.ContentResDTO(t, COUNT(DISTINCT c.cmtID), COUNT(DISTINCT r.rctId)) " +
            "FROM TMnTrContent t LEFT JOIN TMnTrComment c ON t.cntID = c.content.cntID LEFT JOIN TMnTrReact r ON t.cntID = r.content.cntID " +
            " WHERE (:cntId IS NULL OR (:cntId IS NOT NULL AND t.cntID = :cntId)) AND " +
            " (:userId IS NULL OR (:userId IS NOT NULL AND t.user.userId = :userId)) " +
            " GROUP BY t.cntID")
    Page<ContentResDTO> findAllBy(@Param("cntId") Long cntId,
                                  @Param("userId") Long userId,
                                  Pageable pageable);

DTO

@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
public class ContentResDTO {
    private long id;
    private long userId;
    private String type;
    private String description;
    private int version;
    private Date createdDate;
    private Date modifyDate;
    private int commentCount;
    private int reactCount;

    public ContentResDTO(TMnTrContent content, long commentCount, long reactCount) {
        this.id = content.getCntID();
        this.userId = content.getUser().getUserId();
        this.type = content.getCntType();
        this.description = content.getCntDescription();
        this.version = content.getVersion();
        this.createdDate = content.getCreateDate();
        this.modifyDate = content.getModifyDate();
        this.commentCount = (int) commentCount;
        this.reactCount = (int) reactCount;
    }

}

0
投票

这里是选项,如果你还需要从origin获取totalElements、totalPages

@Component
@RequiredArgsConstructor
public class CreditIssuedMapper {

public static CreditIssuedDto toCreditIssuedDto(CreditIssued creditIssued){

    CreditIssuedDto c = new CreditIssuedDto();

    c.setId(creditIssued.getId());

    c.setClientId(creditIssued.getClientData().getId());
    c.setClientName(creditIssued.getClientData().getClientName());
    c.setClientSurname(creditIssued.getClientData().getClientSurname());
    c.setClientMiddlename(creditIssued.getClientData().getClientMiddlename());

    c.setManagerId(creditIssued.getManagerData().getId());
    c.setManagerName(creditIssued.getManagerData().getManagerName());
    c.setManagerSurname(creditIssued.getManagerData().getManagerSurname());
    c.setManagerMiddlename(creditIssued.getManagerData().getManagerMiddlename());

    c.setCreditIssuedBody(creditIssued.getCreditBody());
    c.setCreditIssuedLeft(creditIssued.getCreditLeft());
    c.setCreditIssuedFine(creditIssued.getCreditFine());
    c.setCreditIssuedMonthlyPayment(creditIssued.getCreditMonthlyPayment());
    c.setCreditIssuedDate(creditIssued.getCreditIssuedDate());
    c.setCreditIssuedNextPayment(creditIssued.getCreditNextPayment());
    c.setCreditIssuedExpDate(creditIssued.getCreditExpDate());

    c.setCreditOfferId(creditIssued.getCreditOfferId().getId());
    c.setCreditOfferName(creditIssued.getCreditOfferId().getCreditName());
    c.setCreditOfferInterest(creditIssued.getCreditOfferId().getCreditInterest());
    c.setCreditOfferFine(creditIssued.getCreditOfferId().getCreditFine());
    c.setCreditOfferCurrency(creditIssued.getCreditOfferId().getCurrencyData().getCurrencyName());

    return c;

}

public Page<CreditIssuedDto> creditIssuedDto (Page<CreditIssued> creditIssued){

    List<CreditIssuedDto> creditIssuedDto = creditIssued
            .stream()
            .map(CreditIssuedMapper::toCreditIssuedDto)
            .collect(Collectors.toList());

    long totalElements = creditIssued.getTotalElements();
    int totalPages = creditIssued.getTotalPages();

    return new PageImpl<>(creditIssuedDto, PageRequest.of(creditIssued.getNumber(), creditIssued.getSize()), totalElements);
}
}
© www.soinside.com 2019 - 2024. All rights reserved.