Выберите DISTINCT + ORDER BY в API критериев JPA 2

у меня класс Lawsuit, которая содержит List<Hearing> С .

мне нужно выбрать все Lawsuits заказывается по дате их Hearings

Я CriteriaQuery как

CriteriaBuilder           cb = em.getCriteriaBuilder();
CriteriaQuery<Lawsuit>    cq = cb.createQuery(Lawsuit.class);
Root<Lawsuit>           root = cq.from(Lawsuit.class);

Я использую distinct чтобы сгладить результаты:

cq.select(root).distinct(true);

Я тут вступить Lawsuit С Hearing

Join<Lawsuit, Hearing> hearing = root.join("hearings", JoinType.INNER);

создать Predicates

predicateList.add(cb.isNotNull(hearing.<Date>get("date")));

и Orders:

orderList.add(cb.asc(hearing.<Date>get("date")));

все работает нормально, если я избегаю distinct, но если я использую его, он жалуется на невозможность заказа на основе полей, которые не находятся в SELECT:

вызвано: org.в PostgreSQL.утиль.PSQLException: ошибка: для SELECT DISTINCT, ORDER BY выражения должны отображаться в списке выбора

на List<Hearing> уже доступен через Lawsuit классы вернулись, поэтому я в замешательстве: как я должен добавить их в список выбора ?

2 ответов


я обнаружил источник проблемы где-то еще, и решение его сделало ненужным делать то, что задано в вопросе; как описано в других ответах, выполнять distinct здесь.

повторяющиеся строки были созданы erroneous left joins, которые были выполнены для коллекций (атрибутов корневого объекта), даже если предикаты не были использованы:

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()));
}

Итак, если вы здесь, потому что у вас такая же проблема,поиск проблемы в соединениях.


вы также можете удалить дубликат через group by на основе столбца первичного ключа корневой таблицы:

 cq.groupBy(root.get("id")); // Assuming that Lawsuite.id is primary key column