java - restresource - Cómo asignar la Página<ObjectEntity> a la Página<ObjectDTO> en spring-data-rest
spring data rest custom controller (6)
Cuando llego a la base de datos con PagingAndSortingRepository.findAll(Pageable)
obtengo la Page<ObjectEntity>
. Sin embargo, quiero exponer los DTO al cliente y no a las entidades. Puedo crear DTO simplemente inyectando una entidad en su constructor, pero ¿cómo asigno las entidades en el objeto Page a los DTO? Según la documentación de Spring, Page proporciona operaciones de solo lectura.
Además, Page.map no es posible, ya que no tenemos soporte para Java 8. ¿Cómo crear la nueva página con objetos asignados manualmente?
Aún puedes usar el Page.map
sin las expresiones 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;
}
});
Al final, no devolverá la página a los usuarios, sino una lista de ObjectDTO, con los detalles de la página en el encabezado, por lo que esta sería mi solución.
ObjectService
public Page<ObjectEntity> findAll (Pageable pageable){
//logic goes here.
Page<ObjectEntity> page = objectRepository.findAll(pageable);
return page;
}
ObjectResource / rest (el punto final expuesto)
@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);
}
La razón para usar esto es para que no necesite duplicar los detalles de la página para ObjectEntity y DTO. Es clave tener en cuenta que una página contiene lo siguiente:
- número de página
- tamaño de página
- numberOfElements
- contenido
El contenido es la lista de objetos devueltos y es lo único que debe asignarse a DTO.
Aquí está mi solución, gracias a @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);
}
});
}
En Spring Data 2, el método de mapa de página toma una función en lugar de un convertidor, pero sigue funcionando básicamente de la misma manera que lo describió @Ali Dehghani.
Utilizando la función:
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;
}
});
Puedes usar Page.map simplemente haciendo esto:
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;
}
Y en java8:
Page<ObjectEntity> entities =
objectEntityRepository.findAll(pageable)
.map(ObjectDto::fromEntity);
Donde fromEntity es un método estático en ObjectDto que contiene la lógica de conversión.