Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert Page<Entity> to PageDTO<EntityDTO>

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?

like image 448
Saurabh Kumar Avatar asked Jun 04 '15 13:06

Saurabh Kumar


People also ask

Can we use entity class as DTO?

Short answer: Entities may be part of a business domain. Thus, they can implement behavior and be applied to different use cases within the domain. DTOs are used only to transfer data from one process or context to another.

How do you map DTO and entity?

Add maven dependencies spring-boot-starter-web dependency for building web applications using Spring MVC. It uses the tomcat as the default embedded container. org. modelmapper dependency is for mapping the DTO to entity and entity to DTO using model mapper.

What is the difference between DTO and entity?

Short answer: Entities may be part of a business domain. Thus, they can implement behavior and be applied to different use cases within the domain. DTOs are used only to transfer data from one processor context to another.


1 Answers

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

}
like image 127
FunnyJava Avatar answered Oct 07 '22 17:10

FunnyJava