2014-11-03 170 views
1

我的房间与SeminarLectures具有多对多关系。 我想要在给定日期获得所有没有讲座的房间。休眠NOT IN子查询

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

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" 

回答

2

如这里记载:

16.13. Subqueries

对于支持子查询的数据库,Hibernate查询中支持子查询。子查询必须用圆括号包围(通常由SQL聚合函数调用)。即使相关的子查询(引用外部查询中的别名的子查询)也是允许的。

片段:

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

所以我们需要明确说什么是不是在

// 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 ...)。大多数情况下,过滤将变得更加简单和直接。

+0

它匹配表中的一行而不是表本身,所以你需要指定哪一列(r.id) – Roger 2014-11-03 16:29:21

+0

我得到了完全相同的错误 – 2014-11-03 16:41:43

+0

我做了'不在'因为'ls。房间'是一个房间对象的列表,所以我想我需要比较房间不IDS与房间 – 2014-11-03 16:42:44