2009-08-17 103 views
3

我想写一个NHibernate的HQL查询,在where子句中使用括号。但是,HQL解析器似乎忽略了我的括号,从而改变了我的陈述的含义。任何人都可以就此事阐明任何事情吗?NHibernate的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

左侧加入您在from子句指定,必须得到尊重在where子句的所有标准中。您必须在查询的所有部分处理特殊的空情况,这就是SQL(和HQL)的工作方式。

参考:http://en.wikipedia.org/wiki/Null_(SQL)

,当你写u.CommunicationPreferences.Email = 0,该CommunicationPreferences必须不为空,或者数据库行不会被选中。

我建议尝试以下(使其适应自己的情况下):从HQL最佳实践对我们的项目

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 

提取物:

  • 它取别名的所有表达到
  • 对于每个可以为空的别名(在这种情况下为w和c),任何约束(c.Email = 0)都必须使用空值(or c is null

添加:要更多地解释:

第二LEFT JOIN要选择WEBUSER手段即使是相匹配的任何CommunicationPreferences。这与u.CommunicationPreferences.Email之类的选择不兼容,如果u.CommunicationPreferences为空,则排除任何匹配(阅读的很好,我没有引用电子邮件列)。

这样的不兼容可能会导致奇怪的翻译,你不明白为什么SQL是以这种方式创建的...修正HQL并再次尝试:-)括号可能会变得正确。

+1

感谢KLE。多一点信息,CommunicationPreferences.Email不会为空。问题是,括号已经从周围的前两个条件转移到围在中间状态,从而改变了查询 – Jon 2009-08-17 13:18:38

+1

我谈论c.Email的空性的语义,但C本身。它可以为空,因为你写了一个左连接。这意味着:如果没有相应的行,则用空值替换所有值。这与c.Email上的任何选择都不兼容,因为它没有选择来自外部的任何c行。总之,外连接和进一步选择是不兼容的。 – KLE 2009-08-20 14:54:40

2

我知道这是一个迟到的答案,但我不得不补充我的两分钱。

在SQL中,运算符优先于或运算符。 所以

(u.CommunicationPreferences.Email = 0 和u.SyncDate不为空),或 u.DateDeleted不是null

相同

communicat2_ .Email = 0和 (webuser0_.SyncDate不为空)或 webuser0_。DateDeleted不为空