Столкнулись ли с пагинацией
Что проверяют
Вопрос кажется формальностью, но по ответу видно уровень. Джун расскажет про LIMIT и OFFSET, мидл добавит, что на глубоких страницах это перестаёт работать и что сортировка без уникального тай-брейкера даёт дубли и пропуски. Отдельно проверяют, знаете ли вы, как пагинация ведёт себя в Spring Data и Hibernate: там есть пара ловушек, про которые обычно читают уже после происшествия на проде.
Как отвечать
Назовите два подхода:
- по смещению:
Pageableв Spring Data, под капотомLIMITиOFFSET. Просто, даёт номер страницы и общее число, но база вынуждена прочитать и отбросить все пропущенные строки, поэтому глубокие страницы дорожают; - по ключу: условие вида
WHERE (created_at, id) < (:lastDate, :lastId) ORDER BY created_at DESC, id DESC. Цена не зависит от номера страницы, но прыгнуть на произвольную страницу нельзя, только вперёд и назад.
Дальше скажите, чем Page отличается от Slice: Page дополнительно выполняет запрос подсчёта, и на большой таблице он часто дороже самой выборки. Если интерфейсу нужна только кнопка «ещё», хватит Slice. И обязательно проговорите, что в ORDER BY входит уникальная колонка: без неё порядок строк с одинаковым значением не определён.
Где спотыкаются
Ставят Pageable на запрос с JOIN FETCH по коллекции. Hibernate не может ограничить строки в базе, потому что одна сущность занимает их несколько, поэтому он тянет весь результат и режет его в памяти, предупредив об этом одной строчкой в логе. Лечится двумя запросами: сначала страница идентификаторов, потом выборка с JOIN FETCH по этому списку.
Сортируют по неуникальному полю. Между двумя запросами строки с одинаковой датой переставляются, и пользователь видит одну запись дважды, а другую не видит вовсе.
Отдают наружу сущность вместо DTO. При сериализации подтягиваются ленивые связи, и получается либо лишний запрос на каждый элемент страницы, либо LazyInitializationException за пределами транзакции.