Я пытаюсь использовать JPA CriteriaBuilder для создания запроса для объекта под названием «TestContact», который имеет соединение «многие ко многим» с другим объектом под названием «SystemGroup», где атрибут для этого соединения называется «группы». Цель запроса — извлечь записи из сущности «TestContact», где атрибут «groups» либо находится в списке, либо пуст.
Код, который я использую, выглядит следующим образом
public List<TestContact> findWithCriteriaQuery(List<SystemGroup> groups) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<TestContact> cq = cb.createQuery(TestContact.class);
Root<TestContact> testContact = cq.from(TestContact.class);
cq.select(testContact);
Path<List<SystemGroup>> groupPath = testContact.get("groups");
// cq.where(groupPath.in(groups));
// cq.where(cb.isEmpty(groupPath));
cq.where(cb.or(cb.isEmpty(groupPath), groupPath.in(groups)));
TypedQuery<TestContact> tq = em.createQuery(cq);
return tq.getResultList();
}
Проблема в том, что этот запрос возвращает только результаты, где группа находится в списке «группы», но по какой-то причине также не возвращает результаты, где группа пуста (т.е. в таблице соединений нет записи)
Если я изменю предложение where на cq.where(cb.isEmpty(groupPath));
, тогда запрос правильно вернет результаты, где группа пуста.
Если я изменю предложение where на cq.where(groupPath.in(groups));
, тогда запрос правильно вернет результаты, в которых группа находится в списке «группы».
Чего я не понимаю, так это почему, когда я пытаюсь объединить эти два предиката с помощью CriteriaBuilder или метода, результаты не включают записи, где группа либо находится в списке, либо пуста.
Атрибут групп в объекте «TestContact» объявляется следующим образом.
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(name = "TEST_CONTACT_GROUPS", joinColumns = { @JoinColumn(name = "CONTACT_ID", referencedColumnName = "CONTACT_ID") }, inverseJoinColumns = { @JoinColumn(name = "GROUP_ID", referencedColumnName = "GROUP_ID") })
private List<SystemGroup> groups;
Поставщик JPA — EclipseLink 2.5.0, сервер приложений Java EE — GlassFish 4, а база данных — Oracle 11gR2.
Может ли кто-нибудь указать, где я ошибаюсь?
Обновить
Я попробовал предложение @Chris, но Eclipse возвращает следующую ошибку на Join<List<SystemGroup>> groupPath = testContact.join("groups", JoinType.LEFT)
Неверное количество аргументов для типа Join; его нельзя параметризовать аргументами >
Глядя на JavaDoc для Join
, он говорит, что параметры типа...
Z - исходный тип соединения, X - целевой тип соединения
Я пробовал Join<TestContact, SystemGroup> groupPath = testContact.join("groups", JoinType.LEFT);
, что затем заставляет Eclipse возвращать следующую ошибку на cb.isEmpty
Несоответствие привязки: универсальный метод isEmpty(Expression) типа CriteriaBuilder неприменим для аргументов (Join). Выведенный тип SystemGroup не является допустимой заменой ограниченного параметра >