2014-11-03 168 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