Spring Data JPA предлагает два подхода к пагинации: Page и Slice. В отличие от
Page, Slice не знает общего количества записей, но всё равно умеет определять, есть ли следующая страница. Как это возможно без COUNT-запроса? На этот вопрос ответил наш эксперт Михаил Поливаха:
Мы уже как-то писали о том, что в Spring Data есть 2 способа вернуть данные в постраничном виде -
Page и Slice. Разница довольно простая - Slice не знает общий размер датасета, который удовлетворяет запросу, а Page знает. Достигается это знание отправкой ещё одного COUNT-запроса в БД.Однако, несмотря на это,
Slice способен ответить на вопрос, есть ли следующая страничка данных:
public interface Slice<T> extends Streamable<T> {
/**
* Returns if there is a next {@link Slice}.
*
* @return if there is a next {@link Slice}.
*/
boolean hasNext();
}
То есть, как минимум,
Slice должен понимать, следующая страничка с данными присутствует, при этом не делая "COUNT".Чтобы реализовать это, Spring Data JPA, например, делает очень простую вещь:
int pageSize = 0;
if (pageable.isPaged()) {
pageSize = pageable.getPageSize();
createQuery.setMaxResults(pageSize + 1);
}
List<Object> resultList = createQuery.getResultList();
boolean hasNext = pageable.isPaged() && resultList.size() > pageSize
То есть, из БД запрашивается не
pageSize, а pageSize + 1, то есть чуть-чуть больше. Ну и дальше простое сравнение - если нашли pageSize, то странички дальше точно нет, а если нашли pageSize + 1, то страничка дальше точно есть (хотя может и меньшего размера).Вот так вот оно работает 😉