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