Хороший вопрос. Вот что я сделал в прошлом (многие вещи вы уже упоминали):
- Проверьте ВЫБРАТЬ пункт присутствует.
- Если это не так, добавьте
select count(*)
- В противном случае проверьте, имеет ли он DISTINCT или агрегатные функции в нем. Если вы используете ANTLR для анализа вашего запроса, можно обойти их, но это довольно сложно. Вероятно, вам лучше всего обернуть все это с помощью
select count(*) from()
.
- Удалить
fetch all properties
- Удалить
fetch
из объединений, если вы разбираете HQL в виде строки. Если вы действительно разбираете запрос с помощью ANTLR, вы можете полностью удалить left join
; довольно беспорядочно проверять все возможные ссылки.
- Удалить
order by
- В зависимости от того, что вы сделали в 1.2 вам необходимо удалить/настроить
group by
/having
.
Вышеупомянутое относится к HQL, естественно. Для запросов Criteria вы вполне ограничены тем, что можете сделать, потому что это не легко поддается манипуляции. Если вы используете какой-то слой-оболочку поверх критериев, вы получите эквивалент (ограниченного) подмножества результатов анализа ANTLR и в этом случае можете применить большинство вышеперечисленных.
Поскольку вы обычно держитесь за смещение вашей текущей страницы и общего количества, я обычно запускаю фактический запрос с заданным лимитом/смещением и запускаю только запрос count(*)
, если число возвращаемых результатов больше или равно limit AND offset равен нулю (во всех остальных случаях я либо запускаю count(*)
раньше, либо все результаты возвращены). Это, конечно, оптимистический подход в отношении параллельных модификаций.
Update (на ручной сборки HQL)
Я не особенно нравится такой подход. При сопоставлении как именованный запрос, HQL имеет преимущество проверки времени сборки (хорошо, время выполнения технически, потому что SessionFactory должен быть построен, хотя это обычно делается во время тестирования интеграции). Когда он генерируется во время выполнения, он выходит из строя во время выполнения :-) Выполнение оптимизации производительности также не так просто.
То же рассуждение применимо к критериям, конечно, но это немного сложнее испортить из-за четко определенного API, а не для конкатенации строк. Построение двух запросов HQL параллельно (с вычисленным одним и «глобальным подсчетом») также приводит к дублированию кода (и, возможно, к большим ошибкам), или заставляет вас писать какой-то оберточный слой сверху, чтобы сделать это за вас. Оба пути далеко не идеальны. И если вам нужно сделать это из кода клиента (как в более API), проблема становится еще хуже.
Я на самом деле pondered quite a bit по этому вопросу. API поиска от Hibernate-Generic-DAO кажется разумным компромиссом; в моем ответе на вышеупомянутый связанный вопрос есть более подробная информация.
+1 Спасибо за эти рекомендации по обработке запроса. Спасибо также за отличную точность, что ** запрос count должен запускаться только после первого запроса **. – KLE
Я обновил свой вопрос, внеся ли вы другой ответ, связанный с новой частью? Мне понравилось много других ваших сообщений, и вы эксперт по java :-) ... – KLE
Спасибо :-) Я обновил свой ответ выше. – ChssPly76