2013-11-27 44 views
8

我使用Hibernate 3.6和MSSQL 2012HQL隐式连接在where子句中产生交叉连接,而不是内部联接

在执行这个HQL

select tbl.state from Property tbl where tbl.state = 1 and tbl.entity.state = 1 and 
tbl.entity.className = 'com....' and tbl.fieldName = 'fieldName' 

我得到这个SQL

select property0_.State as col_0_0_ from Properties property0_ cross join Entities 
entity1_ where property0_.refEntityid=entity1_.id and property0_.State=1 and 
entity1_.State=1 and entity1_.ClassName='com....' and property0_.FieldName='fieldName' 

*请注意交叉连接在where子句中添加了条件

根据Hibernate的文档https://docs.jboss.org/hibernate/core/3.5/reference/en/html/queryhql.html#queryhql-joins-forms

隐含的加入应该产生于内加入

我注意到有一个开放的错误https://hibernate.atlassian.net/browse/HHH-7707可能是指这个问题,但没有人回答,它已经打开了一年。

我很感谢这个问题的任何信息。谢谢。

PS。我很清楚,使用隐式连接不是编写HQL的正确方式,但我现在无法对此做任何事情。

+1

哇,这真的很蹩脚,在休眠的部分破碎。 '如果foo.bar不为空或foo.bar.baz = x'返回一个完全不合逻辑的零结果,如果所有的foo对象都有一个空栏参考... – Gus

回答

9

你的加入是内连接,但使用旧的语法包括在where子句中添加一个条件:

where property0_.refEntityid=entity1_.id 

,而不是与

inner join Entities entity1_ on property0_.refEntityid=entity1_.id 

结果这样做是完全相同。

只要你明白他们在做什么,在HQL中使用隐式连接并不是一个问题。

+0

你说的一切都很好,但它不能解释为什么我' m交叉加入+添加条件,而不是正常的内部联接像文档说的。 – Rotem

+1

阅读完您的答案之后,我回到了休眠文档中的“连接语法形式”部分,并重新阅读了几次。现在我开始意识到,在那里使用的术语“内部连接”并不意味着内部连接语法,而只是对于可以以两种方式完成的内部连接操作而言,适当的内部连接或交叉连接以及添加的where子句。现在,我可以回到吃饭,睡觉和洗澡,让它去。谢谢@ jb-nizet – Rotem

+0

有关信息,我有一个三重交叉连接,添加where子句,检查EXPLAIN后,我可以确认我得到完全相同的执行计划。当我看到一些其他帖子谈论那些由休眠生成的交叉连接是坏的并且正在改变它们的标准请求时,我感到恐慌了一点......实际上没有任何事情,幸运的是我在这里结束了:-) – Walfrat

0

当使用HQL,执行联结operations.Your查询应该是这样的,当总是使用正确的别名:

select tbl.state 
from Property tbl 
left join tbl.entity entity 
where tbl.state = 1 
    and entity.state = 1 
    and entity.className = 'com....' 
    and tbl.fieldName = 'fieldName' 

否则,如果您尝试使用tbl.entity.someProperty,在HQL,它总是会创建一个交叉连接