SELECT DISTINCT + ORDER BY в JPA 2 Критерии API
У меня есть класс Lawsuit
, содержащий List<Hearing>
, каждый из которых имеет атрибут Date
.
Мне нужно выбрать все Lawsuit
, упорядоченные по дате их Hearing
s
У меня есть CriteriaQuery, например
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Lawsuit> cq = cb.createQuery(Lawsuit.class);
Root<Lawsuit> root = cq.from(Lawsuit.class);
Я использую отличный, чтобы сгладить результаты:
cq.select(root).distinct(true);
Затем я присоединяюсь к Lawsuit
с помощью Hearing
Join<Lawsuit, Hearing> hearing = root.join("hearings", JoinType.INNER);
создать Predicate
predicateList.add(cb.isNotNull(hearing.<Date>get("date")));
и Order
s:
orderList.add(cb.asc(hearing.<Date>get("date")));
Все работает отлично, если я избегаю distinct
, но если я его использую, он жалуется на невозможность заказа на основе полей, которые не находятся в SELECT:
Вызывает: org.postgresql.util.PSQLException: ОШИБКА: для SELECT DISTINCT
выражения ORDER BY
должны отображаться в списке выбора
List<Hearing>
уже доступен через возвращаемые классы Lawsuit
, поэтому я запутался: как добавить их в список выбора?
Ответы
Ответ 1
Я обнаружил источник проблемы где-то в другом месте, и решение этого вопроса сделало ненужным делать то, что было задано в вопросе;
как описано в других ответах, здесь нет необходимости выполнять distinct
здесь.
Дублированные строки были вызваны ошибочным left join
, которые были выполнены в коллекциях (атрибуты корневого объекта), даже если предикаты не были использованы:
Join<Lawsuit, Witness> witnesses = root.join("witnesses", JoinType.LEFT);
if (witnessToFilterWith!=null) {
predicateList.add(cb.equal(witnesses.<Long>get("id"),witnessToFilterWith.getId()));
}
Очевидно, что join
выполняется как inner
и только при необходимости:
if (witnessToFilterWith!=null) {
Join<Lawsuit, Witness> witnesses = root.join("witnesses", JoinType.INNER);
predicateList.add(cb.equal(witnesses.<Long>get("id"),witnessToFilterWith.getId()));
}
Итак, если вы здесь, потому что у вас такая же проблема, найдите проблему в объединениях.
Ответ 2
Вы также можете удалить дубликаты через группу на основе столбца первичного ключа корневой таблицы:
cq.groupBy(root.get("id")); // Assuming that Lawsuite.id is primary key column