Hibernate NOT IN子查询

时间:2014-11-03 16:09:49

标签: java hibernate subquery

我有与SeminarLectures有多对多关系的房间。 我想让所有在特定日期都没有讲课的房间。

为什么这个hibernate查询不起作用?

SELECT r FROM Room as r
WHERE r NOT IN
    (SELECT DISTINCT ls.rooms FROM SeminarLecture AS ls
    WHERE ls.date <> :date)

我明白了:

Syntax Error in ...; expected "*, NOT, EXISTS, INTERSECTS, SELECT, FROM"

1 个答案:

答案 0 :(得分:2)

如此处所述:

16.13. Subqueries

  

对于支持子选择的数据库,Hibernate支持查询中的子查询。子查询必须用括号括起来(通常通过SQL聚合函数调用)。甚至允许相关子查询(引用外部查询中的别名的子查询)。

片段:

from DomesticCat as cat
where cat.name not in (
    select name.nickName from Name as name
)

所以我们需要明确说明什么是NOT IN

// instead fo this
// WHERE r NOT IN
// we have to say what is not IN
WHERE r.id NOT IN
    (SELECT DISTINCT ls.rooms FROM SeminarLecture AS ls
    WHERE ls.date <> :date)

其他选项是使用NOT EXISTS (但是我们应该用一些匹配来扩展内部WHERE子句)

EXTEND:

因为我们面对many-to-many关系,所以我们的HQL必须更加智能,而生成的SQL语句将是位矫枉过正。这是many-to-many映射的副作用,我建议避免(参见here

所以,让我们期待像这样的实体模型:

public class Room {
    ...
    @ManyToMany(....
    public Set<SeminarLecture> getSeminarLectures() {
        return this.seminarLectures;
    }

还有反向结束:

public class SeminarLecture {
    ...
    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "seminarLectures")
    public Set<Room> getRooms() {
        return this.rooms;
    }

然后我们需要的HQL就像这样:

SELECT r FROM Room as r
WHERE r.ID NOT IN
    (SELECT DISTINCT r.ID 
       FROM SeminarLecture AS ls
       JOIN ls.rooms r
       WHERE ls.date <> :date)

就是这样。我们从内部子查询中选择房间ID,并将其与外部查询中的相同ID进行比较。

我的建议/方法是避免many-to-many。映射为一级公民的显式配对表将为我们提供更多。我们可以在这个连接表上引入更多属性(Order,IsMain ......)。而且大多数情况下,过滤将变得更加简单和直接。