问题
I'm trying to write an NHibernate HQL query that makes use of parenthesis in the where clause. However, the HQL parser seems to be ignoring my parenthesis, thus changing the meaning of my statement. Can anyone shed any light on the matter?
The following HQL query:
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
translates to:
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
Thanks
Jon
回答1:
I know this is a late answer but I had to add my two cents.
In SQL the and operator takes precendence over the or operator. So
(u.CommunicationPreferences.Email = 0 and u.SyncDate is not null) or u.DateDeleted is not null
is the same as
communicat2_.Email = 0 and (webuser0_.SyncDate is not null) or webuser0_.DateDeleted is not null
回答2:
The left join that you specify in the from clause, must be respected in all criterias in the where clause. You must take care of the special null case in all parts of the query, this is the way SQL (and HQL) works.
Reference : http://en.wikipedia.org/wiki/Null_(SQL)
when you write u.CommunicationPreferences.Email = 0
, the CommunicationPreferences must be not null, or the database row will not be selected.
I suggest trying the following (adapt it to your own case) :
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
Extract from the HQL Best-practices on our projects :
- give aliases to all tables reached
- for each nullable alias (w and c in this case), any constraint (
c.Email = 0
) must be or-ed with the null case (or c is null
)
Added: To explain more :
The second LEFT join means that you want to select a WebUser even if there is no CommunicationPreferences that match. This is incompatible with a selection like u.CommunicationPreferences.Email
, that excludes any match if u.CommunicationPreferences is null (read well, I don't refer to the Email column).
Such an incompatibility may cause strange translations, where you don't understand why the SQL was created that way ... Fix the HQL and try again :-) The parenthesis may become correct.
来源:https://stackoverflow.com/questions/1287300/nhibernate-hql-logic-problem