Hibernate/JPA:如何强制隐式连接使用 LEFT OUTER JOINS

Posted

技术标签:

【中文标题】Hibernate/JPA:如何强制隐式连接使用 LEFT OUTER JOINS【英文标题】:Hibernate/JPA: How to force implicit joins to use 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'

【问题讨论】:

【参考方案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 查询中需要该属性时,据我所知,它没有影响。

以上是关于Hibernate/JPA:如何强制隐式连接使用 LEFT OUTER JOINS的主要内容,如果未能解决你的问题,请参考以下文章

如何使用休眠将mysql与Java连接?例外:没有名为 org.hibernate.tutorial_jpa 的 EntityManager 的持久性提供程序 [关闭]

Hibernate JPA 没有在 ManyToMany 关联上创建连接表

Hibernate/JPA 注释中的多列连接

Hibernate/JPA @OneToOne 返回空指针异常

hibernate jpa将两个表与另一个表连接起来

Hibernate/JPA 自动创建数据库(MySQL)