2010-08-18 3 views
7

Ich habe vier Tabellen:HQL: Fetch Registriert Kollektionen von Eager Tabelle

RootNode // Will return multiple root nodes 
SubNode // Will return one sub node per root node 
SubNodeChildren1 // Will return multiple for each sub node 
SubNodeChildren2 // Will return multiple for each sub node 

und eine ähnliche Einheit Struktur:

RootNode -> SubNode -> SubNodeChildren1 
        -> SubNodeChildren2 

Ich brauche eine Abfrage, die mit all den RootNodes in der Tabelle zurück seine SubNode und SubNode Kinder initialisiert. Die SubNode wird eifrig geholt, aber die SubNode Kinder werden faul geholt.

Ich weiß, wie man eine Abfrage schreibt, die LEFT OUTER JOIN FETCH die unmittelbaren Kinder einer Tabelle und sie entsprechend initialisieren wird. Ich habe jedoch keine Ahnung, wie man die Kinder eines Tisches ergreift, der eifrig vom obersten Tisch geholt wird.

Ich habe versucht, so etwas wie:

SELECT rn FROM RootNode AS rn LEFT OUTER JOIN FETCH rn.SubNode.SubNodeChildren1 

aber das gibt mir immer einen Fehler, dass der Eigentümer nicht Teil der SELECT ist.

Jede Hilfe wird sehr geschätzt.

Antwort

11

geht hier Hibernate Referenz

Der einzige Grund, warum wir einen Alias ​​benötigen könnten, ist wenn wir rekursiv wird, um eine weitere Sammlung

Welche Ihre Anfrage impliziert neu geschrieben Abrufen join werden soll

select distinct 
    rn 
from 
    RootNode rn 
left join fetch 
    rn.subNode sn 
left join fetch 
    sn.subNodeChildren 

Sie können entweder

deaktivieren Standardunterknoten holen = FetchType.EAGER und einfach abrufen, was Sie wirklich wollen, indem Sie HQL Abfrage - überschreibt effektiv die äußere Verknüpfung und faul Erklärungen der Dateizuordnungs It (HQL Abfrage) für Verbände und Sammlungen (Hibernate Referenzdokumentation). Dieser Ansatz wird von POJO in Action Book unterstützt.

oder die Sammlung von SubNodeChildren als Abruf enable = FetchType.EAGER

Das folgende ist aus dem Hibernate FAQ extrahiert wurde (Der Link wurde deaktiviert (Soweit ich weiß), aber ich habe gerettet, bevor er verschwand)

Wie können wir in einer MVC-Anwendung sicherstellen, dass alle Proxies und faulen Auflistungen initialisiert werden, wenn die Ansicht versucht, auf sie zuzugreifen?

Ein möglicher Ansatz besteht darin, die Sitzung beim Weiterleiten an die Ansicht offen zu lassen (und Transaktion nicht festgeschrieben). Die Sitzung/Transaktion würde geschlossen/übergeben, nachdem die Ansicht zum Beispiel in einem Servlet-Filter gerendert wurde (ein anderes Beispiel würde den ModelLifetime.discard() - Callback in Maverick verwenden). Eine Schwierigkeit bei diesem Ansatz besteht darin, sicherzustellen, dass die Sitzung/Transaktion geschlossen/zurückgesetzt wird, wenn beim Rendern der Ansicht eine Ausnahme auftritt.

...

Ein weiterer Ansatz besteht darin, einfach die Initialisierung aller benötigten Objekte zu erzwingen Hibernate.initialize() verwenden. Das ist oft einfacher als es sich anhört.

+0

+1 Ich frage mich, warum [verschachtelte Join-Fetches] (http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Nested_Joins) in JPA nicht erlaubt sind. –

1

Um die Abfrage zum Laufen zu bringen, hatte ich ein INNER JOIN FETCH anstelle ein LEFT OUTER JOIN FETCH auf der eifrige Einheit zu tun:

SELECT rn FROM RootNode AS rn INNER JOIN FETCH rn.SubNode AS sn LEFT OUTER JOIN FETCH sn.SubNodeChildren1 LEFT OUTER JOIN FETCH sn.SubNodeChildren2 ... 

Um ehrlich zu sein, ich bin immer noch nicht ganz sicher, warum es mit einem INNER JOIN FETCH vs einem LEFT OUTER JOIN FETCH, aber es funktioniert definitiv genau so, wie ich es brauche.

+0

Ok (+1) Nur aus Neugier: Wäre es möglich, dass Sie Ihr Code-Snippet zwischen ** sessionFactory.openSession() und session.close() ** anzeigen? Und deine kommentierte Zuordnung ??? –

+0

Wow, das ist peinlich ... Ihre ursprüngliche Antwort war richtig. Das Code-Snippet 'LINK OUTER JOIN FETCH rn.SubNode AS sn' war das, das ich brauchte, damit meine Entitäten korrekt funktionierten. (All diese Verwirrung war auf ein Problem mit meiner Testumgebung zurückzuführen) –