8

I am using spring data JPA.

my controller looks like following

    @RequestMapping(value = "/pages/{pageNumber}", method = RequestMethod.GET, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<Page<User>> paginatedUser(@PathVariable final Integer pageNumber)
    {
        final PageRequest request = new PageRequest(pageNumber - 1, DEFAULt_PAGE_SIZE, Sort.Direction.DESC, "startTime");
        return new ResponseEntity<>(userRepository.findAll(request), HttpStatus.OK);
    }

Now i decided to send instead of Page object, a PageDTO object to restrict things from sending.Is there any way i can convert Page to PageDTO using java 8.

I saw Page is derived from Iterable So i guess i can do something like following but not sure how to put it together with PageDTO and UserDTO.

StreamSupport.stream(userRepository.findAll(request).spliterator(),false)

is there any effecient java 8 way to do this.

I came up with this solution

     @RequestMapping(value = "/pages/{pageNumber}", method = RequestMethod.GET, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
     public ResponseEntity<PageDTO> paginatedUser(@PathVariable final Integer pageNumber)
        {
            final PageRequest request = new PageRequest(pageNumber - 1, DEFAULt_PAGE_SIZE, Sort.Direction.DESC, "startTime");
            final Page<User> page = userRepository.findAll(request);
            return new ResponseEntity<>(new PageDTO(page, StreamSupport.stream(page.getContent().spliterator(), true).map(UserDTO::new)
                    .collect(Collectors.toList())), HttpStatus.OK);
        }


public class PageDTO {

    private int beginIndex;

    private int currentIndex;

    private int endIndex;

    private List<?> entities;

    public PageDTO(final Page<?> page, final List<?> entities) {
        this.entities = entities;
        this.currentIndex = page.getNumber() + 1;
        this.beginIndex = Math.max(1, currentIndex - 5);
        this.endIndex = Math.min(beginIndex + 10, page.getTotalPages());
    }

Would like to know if there is another effecient way to do this?

Saurabh Kumar
  • 16,353
  • 49
  • 133
  • 212
  • I think this could help you https://stackoverflow.com/questions/39036771/how-to-map-pageobjectentity-to-pageobjectdto-in-spring-data-rest – Vivek Kurmi Sep 28 '18 at 09:31

2 Answers2

12

I know this is an old question, but I ran into the same problem and I'd like to provide a possible solution to whomever may be interested. Here is what I found that helped me with my code: https://github.com/pkainulainen/spring-data-jpa-examples/blob/master/query-methods/src/main/java/net/petrikainulainen/springdata/jpa/todo/TodoMapper.java

I also used JpaRepository which paginates the data, so that the DTO page will have the same parameters (page number, size etc). Here is my repository:

@Repository
public interface Repository extends JpaRepository<Entity, Integer> {

    /**
     * Name the method according to what query you need to execute
     * e.g. findAll --> return all the rows that satisfy the following conditions,
     * ByUsername --> username is a field in entity class,
     * @param pageable: pagination is applied on the data.
     * @return 
     */
    public Page<Entity> findAllByUsername(String username, Pageable pageable);

}

This is the method where I do the mapping:

public Page<EntityDTO> findByUsername(String username, Pageable pageable){
    Page<Entity> entityPage = entityRepository.findAllByUsername(username, pageable);
    List<EntityDTO> dtos = mapper.entityToEntityDTOs(entityPage.getContent());
    return new PageImpl<>(dtos, pageable, entityPage.getTotalElements());
}

And my Mapstruct mapper:

import org.mapstruct.factory.Mappers;

/**
 * Mapper for converting entity to DTO.
 */
@Mapper(componentModel = "spring", uses = {})
public interface Mapper {

    /**
     * The interface declares a member INSTANCE, providing clients access to the mapper implementation,
     * which is the file target\generated-sources\com\company\springapp\dto\mappers\MapperImpl.java
     * (automatically generated when compiling the project).
     */
    AuditMapper INSTANCE = Mappers.getMapper( Mapper.class );

    /**
     * Convert entity to DTO.
     * Mappings are used to 'bind' entity fields to DTO fields (for the mapper's implementation).
     * @param entity
     * @return 
     */
    @Mappings({
        @Mapping(source = "id", target = "id"),
        @Mapping(source = "username", target = "dtoUsername"),
        @Mapping(source = "action", target = "dtoAction")
    })
    public EntityDTO entityToEntityDTO(Entity entity);

    /**
     * Convert entities' list to DTOs' list.
     * @param entities
     * @return 
     */
    public List<EntityDTO> entitiesToEntityDTOs(List<Entity> entities);

}
FunnyJava
  • 446
  • 1
  • 6
  • 17
1

It's a too late answer, but this solution worked for me

Service

public Page<EntityDto> getAllEntities(Pageable pageable) {
    return entityRepository.findAll(pageable).map(entityMapper::toEntityDto);
}

Mapper

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

this will return a list of entities with size = 10 from the first page

http://localhost:port/api/entities?page=0&size=10

Thanks to JHipster!

hakima maarouf
  • 1,010
  • 1
  • 9
  • 26