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 关联上创建连接表