TGViewer
Spring АйО Spring АйО @spring_aio · 11K subscribers
Post #287 4.94K
❓#ВопросЭксперту: почему в Spring Data JDBC отсутствует пагинация для native query?

Отвечает эксперт сообщества Spring АйО – Михаил Поливаха.

–––

Вопрос действительно интересный, и хотя такая возможность могла бы быть полезной, здесь есть свои нюансы и подводные камни. Давайте разберёмся, какие именно.

Начнём с того, что native query — это запросы, написанные на чистом SQL. В Hibernate их часто используют, когда возможностей HQL/JPQL недостаточно или когда нужны специфичные фичи для конкретной СУБД. Однако ни один ORM-фреймворк (будь то Spring Data JDBC, Hibernate или любой другой) не может на 100% знать структуру вашего нативного запроса — он может лишь предполагать. В таком запросе может быть что угодно, и ORM-фреймворк не всегда сможет корректно с ним работать.

Теперь представьте ситуацию: у нас есть Spring Data JPA native query для PostgreSQL и следующий набор тестов:


@Query(
value = "SELECT * FROM users FOR UPDATE SKIP LOCKED;",
nativeQuery = true
)
List<User> findBySomething(String name, Pageable pageable);

@Test
void testWithoutSort() {
userRepository.findBySomething("another", PageRequest.of(1, 10));
}

@Test
void testWithSort() {
userRepository.findBySomething("another", PageRequest.of(1, 10, Sort.by("name")));
}


Первый тест пройдёт успешно, а второй — нет. Почему?

Во втором случае передаётся параметр сортировки через Pageable. Но у jakarta.persistence.Query нет API для установки сортировки, хотя её всё же необходимо учесть. Другими словами, JPA-ровайдер не может нам тут помочь, т.к. он не предоставляет возможности прогнать параметры сортировки через свой API.

В итоге вставлять сортировку в native запрос приходится Spring Data JPA, и ей в буквальном смысле надо угадывать, куда же в запросе поставить ORDER BY. Да, Spring Data JPA может модифицировать ваши native query (существует даже API, позволяющий делать это динамически). Как вы можете догадаться, в данном случае Spring Data JPA не угадает с позиционированием.

Вот пример SQL, который будет сгенерирован в упавшем тесте


SELECT
*
FROM
users
OFFSET
? ROWS
FETCH NEXT ? ROWS ONLY FOR UPDATE SKIP LOCKED;
ORDER BY
FOR.name ASC -- НЕПРАВИЛЬНО! ORDER BY ЗДЕСЬ БЫТЬ НЕ ДОЛЖНО!


Проблема заключается в том, что Spring Data JPA вставляет ORDER BY в неподходящее место, что и приводит к ошибке.

С нативными запросами ORM-фреймворки, такие как Spring Data JPA и Hibernate, вынуждены догадываться, куда вставить OFFSET, LIMIT и ORDER BY. Чаще всего они угадывают верно, так как эти конструкции обычно находятся в конце запроса, но бывают исключения.

Таким образом, поддержка пагинации для нативных запросов — действительно полезная функция, но нужно понимать, что её реализация может привести к множеству багов, связанных с неверным определением позиции для OFFSET, LIMIT и ORDER BY.

Тем не менее, мне кажется, что эта фича стоит того, чтобы её внедрить! Делитесь своим мнением в комментариях, буду рад обсудить!

🖥 Исходный код поста на GitHub.
  • 👍 32
  • ❤ 10
  • 🔥 7
More from @spring_aio
  1. Oct 11, 2026🎬 Записи докладов с JPoint 2026 уже в открытом доступе JUG Ru Group выложили записи с про…
  2. Oct 9, 2026👩‍💻 Kotlin получил почти настоящие статики Начиная с Kotlin 2.5.0-Beta1 можно эксперимен…
  3. Oct 8, 2026🍃 Spring Boot ломает совместимость, G1 тормозит микросервисы, Java долго релизит фичи | S…
  4. Oct 6, 2026👩‍💻 Spring Config Import без магии У наших друзей из Axelix вышла статья о том, как Spri…
  5. Oct 5, 2026🥲 В Java 27 TLS научился переживать квантовую атаку При установке HTTPS-соединения клиент…
  6. Oct 3, 2026⚡️⚡️Строки кода стремятся подешеветь до цены токена. Что остается ценным? Про это — трек «…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →