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

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

而且,Page.map 不可能,因为我们不支持 java 8。如何使用映射对象手动创建新的 Page?

66660 次浏览

你仍然可以使用没有 lambda 表达式的 Page.map:

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;
}
});

这里是我的解决方案,感谢@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);
}


});
}

在 java8中:

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

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

在 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;
}
});

最后,您不会将 Page 返回给用户,而是返回一个 ObjectDTO 列表,页眉处有 Page 的详细信息,因此这将是我的解决方案。

ObjectService

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 的页面详细信息。需要注意的关键是,一个页面包含以下内容:

  • 页码
  • 页面大小
  • NumberOfElements
  • 内容

内容是返回的对象列表,是唯一需要映射到 DTO 的对象。

您可以通过以下方法使用 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;
}

我创建并使用模型映射器,泛型和常用的 lambdas 解决方案。

/**
* 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 类中使用此方法,并且可以根据您的体系结构在服务和控制器上的 Page 转换中对所有实体/dto 重用此方法。

例如:

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

使用 lambda 表达式更方便

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

这在 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的 Page type 中不再支持转换器。另外,函数应该从 java.util.Function 中使用。功能。

使用 Java8Lambda,对我来说很有用。上面已经给出了答案,我只是简化了一下。

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




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

在这里,EmployeeEntityToDto ()是一个将实体转换为 Dtos 的方法

public EmployeeDto employeeEntityToDto(EmployeeEntity entity){
EmployeeDto employeeDto =  new EmployeeDto();
employeeDto.setId(entity.getId());
employeeDto.setName(entity.getName());
return employeeDto;
}
Page<Order> persistedOrderPage = orderQueryRepository.search();


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