2012-04-18 15 views
5

Ich versuche, Hibernate zu verwenden, um ungefähr 100 Millionen Zeilen aus einer Tabelle abzurufen. Ich habe eine persistente Entität, die eine Sammlung von Gebühren enthält (eine andere persistente Entität). Vorausgesetzt, dass ich werde iterieren über das Ergebnis und Zugriff auf die Gebühren für jedes Objekt, möchte ich eifrig Gebühren abholen, um das n + 1 Problem zu vermeiden.Eager holen Sammlungen in Hibernate mit ScrollableResults

Ich sollte auch erwähnen, dass ich es zu einer anderen Tabelle namens Provider (Eins-zu-eins-Zuordnung aber kein Fremdschlüssel) beitreten möchte. Ich habe versucht:

String query = "select new " + Order.class.getName() 
      + "(i, p) from Item i left join fetch i.fees f, Provider p where " 
      + "p.factoryId=i.factoryId and p.factoryRef=i.factoryRef"; 

return session.createQuery(query).scroll(); 

Meine Order-Klasse enthält ein Provider-Feld und ein Item-Feld. Ich bekomme diese Fehlermeldung:

Caused by: org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list

Ich mag würde mit einer Liste der Ordnung, um am Ende der Artikel enthalten (mit den Gebühren eifrig geholt) und Provider.

Antwort

1

Dieser Code von SelectClause verursacht Sie sich die Mühe:

if (!fromElementsForLoad.contains(origin)) { 
         throw new QueryException(
           "query specified join fetching, but the owner " + 
           "of the fetched association was not present in the select list " + 
           "[" + fromElement.getDisplayText() + "]" 
         ); 

Wie Sie sehen können, wenn der Abruf Stichwort erwähnt wird, überprüft überwintern, um zu sehen, ob Sie für den Abruf eingerichtet Feld Eltern gefragt. fromElementsForLoad.contains(origin)

Sie haben es wahrscheinlich getan, um Sie davor zu schützen, einen redundanten Join zu machen, der Sie viel Leistung kosten wird. Es ist eine gute Sache, denn es gibt keinen Grund, die Assoziation zu holen, wenn man sie nie benutzt.

Ich glaube, dass in Ihrem Fall - Umhüllen der Item.class in der neuen Order.class verbirgt die Tatsache, dass Sie die Fetch dekorierten Feld Eltern in der Abfrage verwenden.

Ich habe keine Debugging-Fähigkeiten im Moment, so kann ich dies nicht validieren. Versuchen Sie, diese exakte Zeile von SelectClause.class zu debuggen und zu sehen, welche Elemente die fromElementsForLoad-Auflistung enthält.

Wenn Sie das n + 1 Problem vermeiden möchten, würde ich empfehlen, die Order.class nach der Abfrage zu initialisieren. Sie können nur den Artikel und den Anbieter auswählen.

Wenn Sie dies nicht bestätigen können, werde ich nächste Woche zu einem geeigneten Computer gehen und meine Antwort erweitern.

+0

Ich denke, diese Antwort ist richtig. Wenn dies der Fall ist, sollten Sie Hibernate wissen lassen können, dass Sie 'Item' tatsächlich holen, indem Sie die Abfrage so ändern, dass eine 'List' zurückgegeben wird, anstatt eine' Order' zu konstruieren: 'select i, p from ...'. Sie müssen dann die Bestellung manuell erstellen. –

0

Versuchen Sie, die left join fetch i.fees f zu entfernen und das eifrige Abrufen im Mapping durchzuführen.

Verwandte Themen