2012-04-18 13 views
5

Sto tentando di utilizzare Hibernate per recuperare circa 100 milioni di righe da una tabella. Ho un oggetto di entità persistente che contiene una raccolta di tasse all'interno (un'altra entità persistente). Dato che I sarà iterare sul risultato e accedere alle tariffe per ogni oggetto, voglio prendere con impazienza le tariffe per evitare il problema n + 1.Eager che recupera le raccolte in Hibernate con ScrollableResults

Vorrei anche dire che voglio unirmi ad un altro tavolo chiamato Provider (mappatura one-to-one ma nessuna chiave esterna). Ho provato:

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(); 

La mia classe Ordine contiene un campo Provider e un campo Articolo. Ottengo questo errore:

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

Vorrei finire con un elenco a scorrimento dell'ordine che contengono Prodotto (con le tasse con entusiasmo recuperati) e Provider.

risposta

1

Questo codice da SelectClause si provoca il disturbo:

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() + "]" 
         ); 

Come si può vedere, quando si parla la parola prendere, ibernazione controlli per vedere se lei ha chiesto per il genitore campo prendere decorato. fromElementsForLoad.contains(origin)

Probabilmente l'hanno fatto per difenderti dal fare un join ridondante che ti costerà molto in termini di prestazioni. È una buona cosa perché non c'è motivo di recuperare l'associazione se non la usi mai.

Credo che nel tuo caso - il wrapping del Item.class nel nuovo Order.class nasconda il fatto che si usi il padre del campo decorato recuperato nella query.

Al momento non ho capacità di debug, quindi non posso convalidarlo. prova a eseguire il debug di questa riga esatta da SelectClause.class e scopri quali elementi contiene la raccolta fromElementsForLoad.

Se si desidera evitare il problema n + 1, si consiglia di inizializzare Order.class dopo la query. È possibile selezionare solo l'articolo e il fornitore.

Se non riesci a convalidarlo, arriverò a un computer corretto la prossima settimana e amplierò la mia risposta.

+0

Penso che questa risposta sia giusta. Se è così, dovresti essere in grado di far sapere ad Hibernate che stai effettivamente recuperando 'Item's cambiando la query per restituire un' List' piuttosto che costruire un 'Ordine':' seleziona i, p da ... '. Dovrai quindi creare l'ordine manualmente. –

0

Provare a rimuovere lo left join fetch i.fees f ed eseguire il richiamo desideroso nella mappatura.

Problemi correlati