Как исправить «элементы ORDER BY должны появляться в списке выбора, если указано SELECT DISTINCT» в JPA и Hibernate - PullRequest
0 голосов
/ 28 февраля 2019

Я работаю в проекте, где одной задачей является создание динамических запросов с возможностью сортировки по атрибутам связанных ленивых сущностей oneToMany.Моя первая попытка была с Criteria-api, но я не мог понять это особенно, когда мне нужно было запросить «несвязанные» поля, поэтому я переключился на простой JPQL, где я мог выразить себя более четко

Однакопохоже, что у простого JPQL тоже есть проблемы.Одним из вариантов использования является выборка AggregateRoots со связанными объектами (например, выборка соединения), где предикаты могут соответствовать значениям атрибутов AggregareRoot или связанных объектов.То же самое относится и к заказываемой части.Теперь результаты должны быть также разбиты на страницы .

Я мог бы реализовать все это, но затем, выполняя запрос, я получил «HHH000104: firstResult / maxResults, указанный при получении коллекции; применение в памяти!».После некоторого поиска в Google я оказался в https://vladmihalcea.com/fix-hibernate-hhh000104-entity-fetch-pagination-warning-message/, где это было объяснено и предложено 2 решения.Первое решение просто запрашивает ID: s AggregateRoots (без выборки соединения), а затем фактический граф данных запрашивается с этими идентификаторами (с выборкой соединения).

Теперь возникает большая проблема, мне нужно иметь возможность сортировать по некоторым полям совокупного корня или по связанным полям сущностей (все продиктовано пользовательским интерфейсом).Моим первым наивным решением было просто «выбрать отличный a.id как идентификатор из AggregateRoot ...», но когда ему потребовалась сортировка, я получил элементы ORDER BY, которые должны появиться в списке выбора, если для SELECT DISTINCT указано .После некоторого удивления я понял, что могу создать проекцию всех возможных полей «сортировки» (AggregateRoot.ID является одним из них, используется в качестве последнего средства в предложении сортировки по, чтобы сделать результаты согласованными), а затем извлечь идентификаторы AggregateRoot оттуда, чтобыпередается фактический запрос данных.Однако теперь я оказался в главной проблеме несоответствия импеданса ORM (как я понимаю).По сути, в итоге у меня есть следующий вид SQL

, который выбирает отличный агрегат0_.id как col_0_0_, связанный с ним_интеграция_имя как col_6_0_ из агрегатного Ag0_Root_агрегата__ внутреннего_предложениясмещение 0 строк, выборка только из следующих 3 строк

, что в итоге приведет к результатам

<html>
<head>
<style>
table, th, td {
  border: 1px solid black;
}
</style>
</head>
<body>
<table>
<tr>
<td><b>col_0_0_</b></td><td><b>col_6_0_</b></td>
</tr>
<tr>
<td>1</td><td>CCC</td>
</tr>
<tr>
<td>1</td><td>BBB</td>
</tr>
<tr>
<td>2</td><td>AAA</td>
</tr>
</table>
</body>
</html>

Так что теперь у меня есть только 2 уникальных идентификатора (вместо 3), которые должны быть переданы в качестве параметра в фактический запрос данных.Я также попытался дать подсказку HINT_PASS_DISTINCT_THROUGH, как описано здесь https://vladmihalcea.com/jpql-distinct-jpa-hibernate/, но все же я получаю только 2 агрегированных корневых идентификатора (hibernate-core является версией 5.4.1.final).Любой совет будет принята с благодарностью!

1 Ответ

0 голосов
/ 28 февраля 2019

Написать производную таблицу для первого запроса:

select t.id 
from (
    select id, col1, col2
    from root_table
    where ...
    order by col1, col2
    fetch first 50 rows only
) t

Используя идентификаторы, извлеченные из этого запроса, вы можете использовать второй JPQL-запрос для объединения извлечения корневых и дочерних объектов, как описано в эта статья .

...