Спецификации Spring Data JPA - Distinct + заказ по столбцу в соединении - PullRequest
0 голосов
/ 20 июня 2020

У меня есть некоторые спецификации, которые я комбинирую с "и":

Specification.where(predicate1).and(predicate2).and(predicate3);

Один из них имеет отдельный набор:

query.distinct(true);

Другой делает заказ по столбцу который находится в соединении.

query.orderBy(builder.desc(bJoin.get("orderbyColumn")));

Это не удается с SQLGrammarException , в котором указано, что порядок по столбцу должен быть отдельным.

Итак, в основном у нас есть объект A, основной объект и некоторая вложенная сущность B, мы выбираем из A, но хотим упорядочить по B, и в сгенерированном sql он выбирает только столбцы из A. Я нашел единственный способ заставить его работать (= выбор из B как хорошо) заключается в замене соединения выборкой:

Fetch < A, B > bFetch = root.fetch("joinCol", JoinType.INNER);
Join < A, B > bJoin = (Join < A, B > ) bFetch;

, которая работала некоторое время, тестировалась локально в H2, но затем через некоторое время начала появляться другая ошибка:

org.hibernate.QueryException: запрос указывает выборку соединения, но владелец выбранной ассоциации не присутствует в списке выбора

Я решил это как-то в моем локальном указателе H2, требуя, чтобы некоторые столбцы не быть нулевым, но на реальном сервере, использующем PostgreSQL, он вообще не работает, получая эту ошибку для всех случаев, когда присутствует выборка.

Мой вопрос: как правильно использовать отличное вместе с порядком для вложенной сущности, которая не извлекается? Мое решение с fetch нормально, и его просто нужно исправить (и если да, то как?), Или мне нужно go для другого варианта полностью?

Для фактического запроса, который я использую этот метод:

findAll(Specification<>, Pageable)

Разве нет способа иметь отличное обертывание всего запроса с помощью order by (своего рода подзапрос?) и обхода всего этого кошмара? Сгенерирует ли он такой запрос:

select distinct colA1, colA2, coAl3 from (select colA1, colA2, coAl3 

from A inner join B b on ........ order by b.colB1)

Нужно ли мне вручную преобразовывать мою спецификацию в предикат и делать с ней что-то еще, чтобы попытаться решить мои проблемы (какой-то гибридный подход)?

Мы будем благодарны за любые советы.

1 Ответ

1 голос
/ 21 июня 2020

Я столкнулся с той же ошибкой, но на самом деле это не была ошибка :)

findAll (Specification <>, Pageable) этот метод выдает 2 разных запроса.

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

Вы можете проверить тип запроса с помощью кода ниже

if (query.getResultType() != Long.class && query.getResultType() != long.class){
   root.fetch("entity1");
} 
...