[英]How to map Page<ObjectEntity> to Page<ObjectDTO> in spring-data-rest
當我使用PagingAndSortingRepository.findAll(Pageable)
訪問數據庫時,我得到了Page<ObjectEntity>
。 但是,我想將 DTO 公開給客戶端而不是實體。 我可以通過將實體注入它的構造函數來創建 DTO,但是我如何將頁面 object 中的實體 map 添加到 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;
}
});
在 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;
}
});
在java8中:
Page<ObjectDto> entities =
objectEntityRepository.findAll(pageable)
.map(ObjectDto::fromEntity);
其中 fromEntity 是 ObjectDto 上包含轉換邏輯的靜態方法。
您可以通過簡單地執行以下操作來使用 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;
}
這是我的解決方案,感謝@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);
}
});
}
我創建並使用帶有模型映射器、泛型和 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 類中使用此方法,並且可以根據您的架構在服務和控制器上的頁面轉換中將其重用於所有實體/dto。
示例:
Page<ObjectDto> dtoPage = mapperUtil.mapEntityPageIntoDtoPage(entities, 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 使用。
使用 lambda 表達式更方便
Page<ObjectDto> dto=objectRepository.findAll(pageable).map((object -> DozerBeanMapperBuilder.buildDefault().map(object, ObjectDto.class)));
Page<Order> persistedOrderPage = orderQueryRepository.search();
Page<OrderDTO> orderPage = persistedOrderPage.map(persistedOrder -> {
OrderDTO order = mapper.toOrderDTO(persistedOrder);
// do another action
return order;
});
最后,您不會將頁面返回給用戶,而是返回一個 ObjectDTO 列表,頁面詳細信息位於標題處,因此這將是我的解決方案。
public Page<ObjectEntity> findAll (Pageable pageable){
//logic goes here.
Page<ObjectEntity> page = objectRepository.findAll(pageable);
return page;
}
@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 的頁面詳細信息。 需要注意的是,頁面包含以下內容:
內容是返回的對象列表,是唯一需要映射到 DTO 的內容。
使用 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;
}
這是一個為時已晚的答案,但這個解決方案對我有用
服務
public Page<EntityDto> getAllEntities(Pageable pageable) {
return entityRepository.findAll(pageable).map(entityMapper::toEntityDto);
}
映射器
import org.mapstruct.Mapper;
@Mapper(componentModel = "spring")
public interface EntityMapper {
EntityDto toEntityDto(Entity entity);
}
Controller
@GetMapping(path = "/entities")
public List<EntityDto> getAllEntities(Pageable pageable) {
Page<EntityDto> page = entityService.getAllEntities(pageable);
return page.getContent();
}
這將從第一頁返回大小 = 10 的實體列表
http://localhost:port/api/entities?page=0&size=10
感謝 JHipster!
我用 Lambda 和ModelMapper
Page<ObjectEntity> pageEntity = objectRepository.findAll(pageable);
Page<ObjectDto> pageDto = pageEntity.map(objectEntity -> modelMapper.map(objectEntity, ObjectDto.class));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.