Boost performance of pagination with infinite scrolling using Slice
Tip submitted by @nkolosnjaji
Pagination with infinite scrolling is using Spring Data Page to retrieve entities from your database.
This will trigger two queries, one to fetch entities and second for count all
to determine the total items for paging. Infinite scrolling doesn’t need information about the total size but only if there is a next page to load. To avoid count all
query which can be an expensive operation when working with large datasets, use Slice instead of Page which will boost performance of infinite scrolling.
We will use a custom HTTP header X-Has-Next-Page
to send information to front-end infinite-scroll plugin.
- Define new method in your Entity repository:
Slice<YourEntity> findSliceBy(Pageable pageable);
- Define new static method in
PaginationUtil.java
located inweb/rest/util
package
public static HttpHeaders generateSliceHttpHeaders(Slice<?> slice) {
HttpHeaders headers = new HttpHeaders();
headers.add("X-Has-Next-Page", "" + slice.hasNext());
return headers;
}
- Modify REST controller to call Slice instead of Page and generate new HTTP headers.
@GetMapping("/<YourEntities>")
@Timed
public ResponseEntity<List<Repo>> getAllRepos(Pageable pageable)
throws URISyntaxException {
Slice<YourEntity> slice = repoRepository.findSliceBy(pageable);
HttpHeaders headers = PaginationUtil.generateSliceHttpHeaders(slice);
return new ResponseEntity<>(slice.getContent(), headers, HttpStatus.OK);
}
- Define new view model in
entity.controller.js
vm.hasNextPage = false;
- Extract HTTP header value from response and assign it to view model in
function onSuccess(data, headers) {
vm.hasNextPage = headers('X-Has-Next-Page') === "true";
...
}
- Use view model with infinite-scroll plugin in
<your-entities>.html
<tbody infinite-scroll="vm.loadPage(vm.page + 1)" infinite-scroll-disabled="!vm.hasNextPage">