如何在 spring-data-rest 中将 Page<ObjectEntity> 映射到 Page<ObjectDTO>
How to map Page<ObjectEntity> to Page<ObjectDTO> in spring-data-rest
当我使用 PagingAndSortingRepository.findAll(Pageable)
访问数据库时,我得到 Page<ObjectEntity>
。但是,我想将 DTO 公开给客户端而不是实体。我可以通过将实体注入它的构造函数来创建 DTO,但是如何将 Page 对象中的实体映射到 DTO?根据 spring 文档,Page 提供只读操作。
此外,Page.map 是不可能的,因为我们不支持 java 8. 如何手动创建带有映射对象的新页面?
您仍然可以使用不带 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);
其中 fromEntity 是 ObjectDto 上包含转换逻辑的静态方法。
在Spring数据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;
}
});
最后,您不会 return 给用户的页面,而是一个 ObjectDTO 列表,页面详细信息在 header,所以这将是我的解决方案。
对象服务
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 是 objects returned 的列表,是唯一需要映射到 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;
}
我创建了解决方案并将其与模型映射器、泛型和 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);
@提示:您可以从 util class 中使用此方法,并且可以根据您的体系结构对服务和控制器上的页面转换中的所有 entity/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 的页面类型不再支持该转换器。此外,该函数应从 java.util.function.Function.
使用
使用 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;
}
Page<Order> persistedOrderPage = orderQueryRepository.search();
Page<OrderDTO> orderPage = persistedOrderPage.map(persistedOrder -> {
OrderDTO order = mapper.toOrderDTO(persistedOrder);
// do another action
return order;
});
当我使用 PagingAndSortingRepository.findAll(Pageable)
访问数据库时,我得到 Page<ObjectEntity>
。但是,我想将 DTO 公开给客户端而不是实体。我可以通过将实体注入它的构造函数来创建 DTO,但是如何将 Page 对象中的实体映射到 DTO?根据 spring 文档,Page 提供只读操作。
此外,Page.map 是不可能的,因为我们不支持 java 8. 如何手动创建带有映射对象的新页面?
您仍然可以使用不带 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);
其中 fromEntity 是 ObjectDto 上包含转换逻辑的静态方法。
在Spring数据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;
}
});
最后,您不会 return 给用户的页面,而是一个 ObjectDTO 列表,页面详细信息在 header,所以这将是我的解决方案。
对象服务
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 是 objects returned 的列表,是唯一需要映射到 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;
}
我创建了解决方案并将其与模型映射器、泛型和 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);
@提示:您可以从 util class 中使用此方法,并且可以根据您的体系结构对服务和控制器上的页面转换中的所有 entity/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 的页面类型不再支持该转换器。此外,该函数应从 java.util.function.Function.
使用使用 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;
}
Page<Order> persistedOrderPage = orderQueryRepository.search();
Page<OrderDTO> orderPage = persistedOrderPage.map(persistedOrder -> {
OrderDTO order = mapper.toOrderDTO(persistedOrder);
// do another action
return order;
});