【问题标题】:Hibernate/JPA: How to force implicit joins to use LEFT OUTER JOINSHibernate/JPA:如何强制隐式连接使用 LEFT OUTER JOINS
【发布时间】:2012-02-18 19:02:39
【问题描述】:

有一个类Offer 与类Article 具有可选 关系。这样一些 offer 文章属性就持有一个null 值。

如果我使用以下语句,一切正常。我得到了所有的报价,即使是那些没有文章的。

SELECT o FROM Offer o 
         LEFT OUTER JOIN o.article a 
         LEFT OUTER JOIN o.vendor v 
         WHERE v.number = '0212' OR a.nummer = '123456'

如果我将语句更改为:

SELECT o FROM Offer o 
         LEFT OUTER JOIN o.article a 
         LEFT OUTER JOIN o.vendor v 
         WHERE v.number = '0212' OR o.article.nummer = '123456'

我只收到了与NULL 不同的文章。这是因为隐式连接 (o.article.nummer) 的表示法强制进行内部连接。

是否有可能强制左外连接到隐式连接(注释驱动或其他)?如果有机会我可以使用这样的简短形式:

SELECT o FROM Offer o 
         WHERE v.number = '0212' OR o.article.nummer = '123456'

【问题讨论】:

    标签: hibernate jpa hql outer-join jql


    【解决方案1】:

    您可以尝试将 @Fetch(FetchMode.JOIN) 放在 Article 属性上。然而,这是一个 Hibernate 注释。

    import org.hibernate.annotations.Fetch;
    import org.hibernate.annotations.FetchMode;
    
    //...
    
    @ManyToOne
    @Fetch(FetchMode.JOIN)
    Article article;
    

    【讨论】:

    • 我不知道这应该如何解决问题。 AFAIK Fetchmode 仅指定如何获取数据以初始化内存中的对象,而不是如何在查询中进行连接。
    【解决方案2】:

    据我所知,Hibernate 没有提供一种方法来更改 HQL 查询的默认隐式关联连接形式。

    我能为自己找到的最佳解决方案是:

    • 使用显式连接信息构建查询;
    • 使用 Criteria,这可能最适合动态查询构建。

    【讨论】:

    • OP 没有说有什么动态的。我错过了什么吗?
    • “0212”和“123456”的用法表明查询在运行时会发生变化。我为“使用正确的 SQL 连接”找到的解决方案之一是使用 Criteria API。而且感觉更自然。
    • Criteria API 通常使用起来更复杂,并且不如 HQL 强大。如果只有值发生变化,只需将参数放入查询中。这不是真正的“动态”,它是参数化的。
    【解决方案3】:

    首先,如果您尝试使用 o.article.nummer 而不是 a.nummer,我相信它会添加一个带有内部连接的额外 WHERE 子句。没有办法明确地说左连接。但是无论如何您都是在查询中自己指定它,所以只需使用别名 a.number = '23456' 中的连接实体。

    由于您知道该字段可以为空,因此您不能使用 =,就像您不能在 SQL 中对可空字段使用 = 一样。为此,请使用 COALESCE 将 NULL 值转换为空字符串:

    SELECT o FROM Offer o 
        LEFT OUTER JOIN o.article a
        LEFT OUTER JOIN o.vendor v 
            WHERE v.number = '0212'
            OR COALESCE(a.nummer,'') = '123456'
    

    【讨论】:

      【解决方案4】:

      我有一个类似的问题:我有某种GeneralFacility-Table,其中包含一个列SpecificType。并非所有设施都具有这种类型,并且由于 SpecificType 是在 GeneralFacility-Table 条目上内部连接的,因此没有特定类型落在表下。

      我解决了这个问题

          @Fetch(FetchMode.SELECT)
      

      在模型中的@ManyToOne-行旁边。该类型现在在单独的查询中获取,如果不返回任何内容,则不会丢弃 GeneralFacility 查询的结果。

      【讨论】:

      • 我猜这仅适用于您获取实体时,例如使用session.get。当您在 HQL 查询中需要该属性时,据我所知,它没有影响。
      猜你喜欢
      • 2022-09-28
      • 1970-01-01
      • 2014-04-18
      • 2020-02-26
      • 2011-06-12
      • 2012-04-29
      • 1970-01-01
      • 1970-01-01
      • 2019-03-08
      相关资源
      最近更新 更多