Выберите DISTINCT + ORDER BY в API критериев JPA 2
у меня класс Lawsuit
, которая содержит List<Hearing>
С .
мне нужно выбрать все Lawsuit
s заказывается по дате их Hearing
s
Я 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);
создать Predicate
s
predicateList.add(cb.isNotNull(hearing.<Date>get("date")));
и Order
s:
orderList.add(cb.asc(hearing.<Date>get("date")));
все работает нормально, если я избегаю distinct
, но если я использую его, он жалуется на невозможность заказа на основе полей, которые не находятся в SELECT:
вызвано: org.в PostgreSQL.утиль.PSQLException: ошибка: для
SELECT DISTINCT
,ORDER BY
выражения должны отображаться в списке выбора
на List<Hearing>
уже доступен через Lawsuit
классы вернулись, поэтому я в замешательстве: как я должен добавить их в список выбора ?
2 ответов
я обнаружил источник проблемы где-то еще, и решение его сделало ненужным делать то, что задано в вопросе;
как описано в других ответах, выполнять distinct
здесь.
повторяющиеся строки были созданы erroneous left join
s, которые были выполнены для коллекций (атрибутов корневого объекта), даже если предикаты не были использованы:
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