我有与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"
答案 0 :(得分:2)
如此处所述:
对于支持子选择的数据库,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 ......)。而且大多数情况下,过滤将变得更加简单和直接。