我正在尝试编写一个NHibernate HQL查询,该查询在where子句中使用括号。但是,HQL解析器似乎忽略了我的括号,从而改变了我的语句的含义。任何人都可以解释这件事吗?
以下HQL查询:
from WebUser u left join fetch u.WebUserProfile left join fetch
u.CommunicationPreferences where (u.CommunicationPreferences.Email = 0 and
u.SyncDate is not null) or u.DateDeleted is not null
转换为:
from WebUser webuser0_
left outer join WebUserProfile webuserpro1_
on webuser0_.UserId = webuserpro1_.WebUserId
left outer join WebUserCommunicationPreferences communicat2_
on webuser0_.UserId = communicat2_.UserId
where communicat2_.Email = 0
and (webuser0_.SyncDate is not null)
or webuser0_.DateDeleted is not null
由于
乔恩
答案 0 :(得分:2)
我知道这是一个迟到的答案,但我不得不加两分钱。
在SQL中,and运算符优先于or运算符。 所以
(u.CommunicationPreferences.Email = 0 和u.SyncDate不为null)或 u.DateDeleted不为空
与
相同communicat2_.Email = 0和 (webuser0_.SyncDate不为null)或 webuser0_.DateDeleted不为空
答案 1 :(得分:0)
您必须在where子句的所有标准中遵守您在from子句中指定的左连接。您必须在查询的所有部分中处理特殊的null情况,这是SQL(和HQL)的工作方式。
参考:http://en.wikipedia.org/wiki/Null_(SQL)
当您编写u.CommunicationPreferences.Email = 0
时,CommunicationPreferences必须不为null,否则将不会选择数据库行。
我建议尝试以下方法(根据您自己的情况进行调整):
from WebUser u
left join fetch u.WebUserProfile w
left join fetch u.CommunicationPreferences c
where ( (c.Email = 0 or c is null)
and u.SyncDate is not null)
or u.DateDeleted is not null
从我们项目的HQL最佳实践中摘录:
c.Email = 0
)都必须使用空案例(or c is null
)已添加:详细说明:
第二个LEFT连接意味着即使没有匹配的CommunicationPreferences,也要选择WebUser。这与u.CommunicationPreferences.Email
之类的选择不兼容,如果u.CommunicationPreferences为null,则排除任何匹配(请仔细阅读,我不参考电子邮件列)。
这种不兼容性可能导致奇怪的翻译,你不明白为什么以这种方式创建SQL ...修复HQL并再试一次:-)括号可能变得正确。