У меня есть следующие таблицы
CREATE TABLE "COMPANIES" (
"ID" NUMBER NOT NULL ,
"NAME" VARCHAR2 (100) NOT NULL UNIQUE
)
/
CREATE TABLE "COMPANIESROLES" (
"ID" NUMBER NOT NULL ,
"COMPANYID" NUMBER NOT NULL ,
"ROLENAME" VARCHAR2 (30) NOT NULL
)
/
CREATE TABLE "ROLES" (
"NAME" VARCHAR2 (30) NOT NULL
)
/
Эта структура представляет количество компаний и роли, разрешенные для каждой компании.Для этих таблиц есть соответствующие объекты Hibernate:
public class Company implements Serializable {
private Long id;
private String name;
private Set<Role> companyRoles;
//(getters and setters omitted for readability)
}
public class Role implements Serializable {
private String name;
//(getters and setters omitted for readability)
}
Найти все компании, которые играют определенную роль, с помощью Hibernate Criteria API, не проблема:
Session session = this.sessionFactory.getCurrentSession();
Criteria criteria = session.createCriteria(Company.class);
criterion = Restrictions.eq("companyRoles.name", "ADMIN");
criteria.add(criterion);
List<Company> companyList = criteria.list();
Hibernate переводитэто к запросу SQL (приблизительно)
SELECT *
FROM companies this_
inner join companyroles cr2_
ON this_.id = cr2_.companyid
inner join roles role1_
ON cr2_.rolename = role1_.NAME
WHERE role1_.NAME = 'ADMIN'
А теперь проблема: как я могу отменить запрос, то есть выяснить все компании, у которых нет сопоставления для роли "ADMIN"?Если я просто попытаюсь отменить критерий, установив
criterion = Restrictions.ne("companyRoles.name", "ADMIN");
(не равно, а не равно), Hibernate создаст запрос, подобный этому
SELECT *
FROM companies this_
inner join companyroles cr2_
ON this_.id = cr2_.companyid
inner join roles role1_
ON cr2_.rolename = role1_.NAME
WHERE role1_.NAME != 'ADMIN'
Очевидно, что это не приводит к желаемомувывод, так как список по-прежнему содержит компании, имеющие роль «ADMIN», при условии, что компании выполняют по крайней мере еще одну роль.
То, что я хочу иметь, это список компаний, которые не имеют роли «АДМИН».В качестве дополнительного ограничения это должно быть выполнимо путем простого изменения объекта Criterion, если это возможно (это происходит потому, что критерий создается автоматически как часть внутренней структуры, и там невозможно вносить более крупные изменения). Решение также должно работать, когда объект Criteria содержит другие дополнительные критерии.
Как это выполнимо, или это так?