JPA с нетерпением ждёт лучших практик
После некоторых исследований я нашел много материалов о том, как написать простой и эффективный код (с использованием JPQL), которые:
- Позволяет активно выбирать связанные объекты (например, используя JOIN FETCH).
- Позволяет нумерацию страниц на одном объекте.
Но когда дело доходит до объединения их обоих - становится неясно, как сделать это эффективным и чистым способом.
Либо это нетерпеливое извлечение, которое работает, но разбиение на страницы применяется в памяти (иначе 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 ответов
Самый простой подход к этой проблеме - использовать два запроса:
- Первый запрос для применения условия where и нумерации страниц. Запрос возвращает только идентификаторы
- Во втором запросе вы используете идентификаторы, возвращенные в первом запросе и делаете
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
предложение должно присутствовать в двух запросах, потому что база данных не соблюдает порядок идентификаторов, который вы передаете параметром, когда база данных возвращает строки.