Hibernate Criteria查询:获取具有m..n关系的对象列表,其中子表没有特定属性

我有以下表格

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 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 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”角色的公司,只要这些公司至少有一个其他角色。

我想要的是一个公司列表,它们没有“ADMIN”角色。 作为一个额外的限制,如果可能的话,只需修改Criterion对象就可以做到这一点(这是因为标准是作为内部框架的一部分自动构建的,并且不可能在那里进行更大的更改)。 当Criteria对象包含其他附加标准时,解决方案也应该有效。

这怎么可行,或者是这样吗?

您需要一个子查询(DetachedCriteria)。

 DetachedCriteria sub = DetachedCriteria.forClass(Company.class); criterion = Restrictions.eq("companyRoles.name", "ADMIN"); sub.add(criterion); sub.setProjection(Projections.property("id")); Criteria criteria = session.createCriteria(Company.class); criteria.add(Property.forName("id").notIn(sub)); List companyList = criteria.list(); 

这样的事情应该做到。