JPA с нетерпением ждёт лучших практик

После некоторых исследований я нашел много материалов о том, как написать простой и эффективный код (с использованием JPQL), которые:

  1. Позволяет активно выбирать связанные объекты (например, используя JOIN FETCH).
  2. Позволяет нумерацию страниц на одном объекте.

Но когда дело доходит до объединения их обоих - становится неясно, как сделать это эффективным и чистым способом.

  • Либо это нетерпеливое извлечение, которое работает, но разбиение на страницы применяется в памяти (иначе HHH000104: firstResult/maxResults, указанный с извлечением коллекции; применение в памяти!)

  • Либо это работает разбиение на страницы, но активная выборка - нет (даже когда resultSet действительно содержит связанные сущности), что приводит к дополнительным запросам к базе данных для извлечения связанных сущностей для каждой строки в пакете.


Самое близкое, что на самом деле работает, это https://vladmihalcea.com/the-best-way-to-fix-the-hibernate-hhh000104-firstresultmaxresults-specified-with-collection-fetch-applying-in-memory-warning-message/

Но это заставило меня задуматься, есть ли более интуитивное и понятное решение проблемы?

Вопрос: Существуют ли другие рекомендации о том, как использовать нумерацию страниц для быстрого поиска связанных объектов?

Примечание. Решение также должно предусматривать способ применения фильтров к данным, извлекаемым из базы данных. (например, предложение JPQL WHERE)

0 ответов

Самый простой подход к этой проблеме - использовать два запроса:

  1. Первый запрос для применения условия where и нумерации страниц. Запрос возвращает только идентификаторы
  2. Во втором запросе вы используете идентификаторы, возвращенные в первом запросе и делаете FETCHо связанных лицах.

Как пример, первый запрос:

String jpql = "SELECT user.id FROM User user WHERE user.name = 'John'"

Query q = em.createQuery(jpql); 
q.setFirstResult(0);
q.setMaxResults(10);

List<Long> ids = q.getResultList();

Второй запрос:

String jqpl = "SELECT user FROM User user JOIN FETCH user.address WHERE user.id IN (:ids)"
Query q = em.createQuery(jpql); 
q.setParameter("ids", ids);

List<User> users = q.getResultList();

Обратите внимание, если вам нужно заказать по какой-то колонке. order by предложение должно присутствовать в двух запросах, потому что база данных не соблюдает порядок идентификаторов, который вы передаете параметром, когда база данных возвращает строки.

Другие вопросы по тегам