【问题标题】:Hibernate NOT IN subqueryHibernate NOT IN 子查询
【发布时间】:2023-03-20 00:20:01
【问题描述】:

我的会议室与 SeminarLectures 具有多对多关系。 我想获取在给定日期没有讲座的所有房间。

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

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"

【问题讨论】:

    标签: java hibernate subquery


    【解决方案1】:

    如此处所述:

    16.13. Subqueries

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

    sn-p:

    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 子句)

    扩展:

    因为我们确实面临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...)上引入更多属性。大多数情况下,过滤将变得更加简单明了。

    【讨论】:

    • 匹配的是表中的一行而不是表本身,所以你需要指定哪一列(r.id)
    • 我做了r NOT IN 因为ls.rooms 是一个房间对象列表,所以我想我需要比较房间而不是房间的ID
    • 如果我删除不同的消息是expected "TOP, LIMIT, DISTINCT, ALL, *, NOT, EXISTS, INTERSECTS, SELECT, FROM"
    • 我发现了你真正的问题.. 这是多对多映射。我总是建议不要使用它......原因正是这种情况,当我们几乎无法过滤这样的集合时......但如果你能给我几分钟......我也许会告诉你如何...... . 同时,你可以检查这个Q&A
    • 我用详细的解释和sn-ps扩展了答案。应该清楚我们必须做什么。但正如我所说,我会避免多对多
    猜你喜欢
    • 2014-03-03
    • 2012-01-17
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    • 1970-01-01
    • 2019-04-01
    • 2021-02-25
    相关资源
    最近更新 更多