Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to modify Page type result of Spring repository search for REST API?

I have a HotelRepository which has a named method which returns a default Page<Hotel> item as result instead of a list.

I want to change the content type Hotel to HotelDto in the page since the DTO has customized parameter that I'd like to display. I have already a constructor to convert Hotel to HotelDto.

My attempt:

Page<Hotel> hotels = dao.findAll(pageRequest);
return new PageImpl<>(
                hotels.getContent().stream()
                        .map(hotel -> new HotelListItemDto(hotel, hotel.getSupplier())).collect(Collectors.toList()),
                pageRequest, hotels.getContent().size());

The problem is that it only manipulate one page of the result. Of course, I can get all the results as a list first then create a page based on the list, but it loses the advantage of Page (I think returning page would improve the performance of the search request).

So what should I do to keep the page advantage but still have the ability to customize the output?

like image 235
LunaticJape Avatar asked Dec 03 '18 19:12

LunaticJape


1 Answers

You almost did it :)

Unless I'm skipping something, the only thing you need to change is the size that you are passing to the PageImpl constructor.

Instead of using hotels.getContent().size() (gives you the size of the content on the actual page) you should use hotels.getTotalElements() which gives you the total size of the elements in all the pages available.

Update 1:

To do it properly, you should change your code for:

Page<Hotel> hotels = dao.findAll(pageRequest);
return new PageImpl<>(
                hotels.getContent().stream()
                        .map(hotel -> new HotelListItemDto(hotel, hotel.getSupplier())).collect(Collectors.toList()),
                pageRequest, hotels.getTotalElements());

The code from above is going to create a page analog to the hotels page. And this is how your parameters are enough for the PageImpl:

  1. The first parameter is the list with the content (of type HotelListItemDemo) that the new page will have. Since this is just a mapping for the hotels content to another type, the number of elements will be exactly the same.
  2. The second parameter is the page request, which gives the PageImpl the information about the page size, the page index (and maybe the order, if you requested one).
  3. The last parameter is the total number of elements that you would have if you append all the pages available in the query (value returned in the hotels.getTotalElements() method). With that, the PageImpl can also calculate things like hasNext() that I mentioned in the comments.

Hope this helps you.

like image 92
Ariel Kohan Avatar answered Sep 30 '22 00:09

Ariel Kohan