3 Stimmen

NHibernate HQL-Logik Problem

Ich versuche, eine NHibernate HQL-Abfrage zu schreiben, die Verwendung von Klammern in der Where-Klausel macht. Der HQL-Parser scheint jedoch meine Klammern zu ignorieren, wodurch sich die Bedeutung meiner Anweisung ändert. Kann jemand etwas Licht in die Angelegenheit bringen?

Die folgende HQL-Abfrage:

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

übersetzt in:

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

Gracias

Jon

2voto

Hank Punkte 21

Ich weiß, dass dies eine späte Antwort ist, aber ich musste meinen Senf dazugeben.

In SQL hat der Operator and Vorrang vor dem Operator or. Also

(u.CommunicationPreferences.Email = 0 und u.SyncDate ist nicht null) oder u.DateDeleted ist nicht null

ist dasselbe wie

communicat2_.Email = 0 und (webuser0_.SyncDate ist nicht null) oder webuser0_.DateDeleted ist nicht null

0voto

KLE Punkte 22895

Die linke Verknüpfung, die Sie in der from-Klausel angeben, muss in allen Kriterien der where-Klausel beachtet werden. Sie müssen den speziellen Null-Fall in allen Teilen der Abfrage berücksichtigen, so funktioniert SQL (und HQL).

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

wenn Sie schreiben u.CommunicationPreferences.Email = 0 Die Kommunikationseinstellungen müssen ungleich Null sein, sonst wird die Datenbankzeile nicht ausgewählt.

Ich schlage vor, Folgendes auszuprobieren (passen Sie es an Ihren eigenen Fall an):

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

Auszug aus den HQL Best-Practices zu unseren Projekten :

  • allen erreichten Tabellen Aliasnamen geben
  • für jeden löschbaren Alias (in diesem Fall w und c), jede Einschränkung ( c.Email = 0 ) muss mit dem Nullfall ( or c is null )

Hinzugefügt : Um mehr zu erklären :

Die zweite LINKS-Verknüpfung bedeutet, dass Sie einen WebUser auswählen wollen, auch wenn es keine passenden CommunicationPreferences gibt. Dies ist unvereinbar mit einer Auswahl wie u.CommunicationPreferences.Email , die jede Übereinstimmung ausschließt, wenn u.CommunicationPreferences null ist (lesen Sie gut, ich beziehe mich nicht auf die E-Mail-Spalte).

Eine solche Inkompatibilität kann zu merkwürdigen Übersetzungen führen, bei denen man nicht versteht, warum die SQL auf diese Weise erstellt wurde ... Korrigieren Sie die HQL und versuchen Sie es erneut :-) Die Klammern werden dann möglicherweise korrekt.

1 Stimmen

Danke KLE. Ein bisschen mehr Info, CommunicationPreferences.Email ist nie null. Das Problem ist, dass die Klammern von den ersten beiden Bedingungen in die mittlere Bedingung verschoben wurden, wodurch sich die Semantik der Abfrage ändert

1 Stimmen

Ich spreche von der Nullbarkeit von c.Email, aber c selbst. Es kann null sein, weil Sie eine linke Verknüpfung schreiben. Das bedeutet: Wenn es keine entsprechende Zeile gibt, werden alle Werte durch Null ersetzt. Dies ist unvereinbar mit jeder Auswahl von c.Email, die zur Folge hat, dass KEINE Zeile von c ausgewählt wird, die aus dem äußeren Teil stammen würde. Kurz gesagt, die äußere Verknüpfung und die weitere Auswahl sind unvereinbar.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X