2011-01-27 10 views
5

oggetto la struttura è come questoRecuperare una struttura grafico in Hibernate

  • fattura
    • clienti
    • Data
    • Numero
    • ha molte ProductLines (prodotto, quantità, prezzo)
    • ha molti ServiceLines (Servizio, Quantità, Prezzo)
    • ha molte paymentOptions (TipoDiPagamento (Controllare, Scontrino fiscale, ecc.), La data, Sum)

Se ho bisogno di recuperare un elenco delle fatture per un determinato periodo con Hibernate è molto facile da fare con pigro caricamento senza scrivere alcun codice basta chiamare get ... MA c'è lo svantaggio di troppe chiamate DB, quindi in un ambiente multiutente questa soluzione non è ok.

Con semplice JDBC ho risolto questo utilizzando 3 query: 3 join tra Fattura e linee di prodotto, fattura e linee di servizio e fattura e opzioni di pagamento. Dopo di ciò ho costruito l'oggetto nella memoria.

Lo stesso può essere fatto con Hibernate lo so, ma la mia domanda è che non esiste un grafico di carico o così posso passare un elenco di fatture e in un numero minimo di chiamate (ottimale) per recuperare i dati?

risposta

4

È possibile utilizzare le query con join fetching, per ottenere l'intero grafo di oggetti in memoria:

Query query = entityManager.createQuery("select distinct invoice from Invoice as invoice " 
      + "left join fetch invoice.productLines "     
      + "left join fetch invoice.serviceLines " 
      + "left join fetch invoice.paymentOptions"); 
for (Object object : query.getResultList()) { 
    // Code here 
} 
+1

Sì, questo è risolvere il problema in una query. L'unico inconveniente è che il prodotto cartesiano di tutte queste tabelle può essere enorme no? – Cris

+1

Infatti. Tuttavia, con questo metodo puoi sempre scegliere quali associazioni recuperare immediatamente e quali caricare pigramente.Quindi è possibile utilizzare la dimensione del batch, come suggerito da Simon, per accelerare i recuperi per i più pigri. –

+1

+1 per l'esempio, che ho aggiunto alla mia risposta. –

4

Potrebbe essere utile considerare batch fetching per le linee della fattura e per il recupero di molte associazioni come ad esempio Cliente.

Questo non ti porta a una chiamata DB, ma se le dimensioni del batch vengono ridotte a un valore leggermente superiore al numero medio di righe di ogni tipo in una fattura, è possibile scendere a una per tipo di linea.

Si potrebbe anche query utilizzando JPQL/HQL ed esplicitamente fetch-unire le linee (as Russ decribes), ma si ottiene un risultato più grande set di quanto si farebbe con un approccio recupero lotto:

Query query = entityManager.createQuery("select distinct invoice from Invoice as invoice " 
      + "left join fetch invoice.productLines "     
      + "left join fetch invoice.serviceLines " 
      + "left join fetch invoice.paymentOptions"); 
for (Object object : query.getResultList()) { 
    // Code here 
} 

Se la dimensione di i dati grezzi trasferiti risultano troppo alti, è possibile disabilitare il recupero esplicitamente rimuovendo "fetch" dalla query nelle posizioni pertinenti.

Nota che esiste un problema di manutenzione utilizzando JPQL perché il compilatore non può controllare tutti i nomi di proprietà per te, e se il recupero è disattivato per tutte le associazioni, la query è un costo netto. Potresti iniziare con il recupero in batch se le prestazioni non sono un problema immediato.

+0

mi ha messo nella giusta direzione (sfortunatamente non posso dare un voto fino dal momento che non sono ancora permesso). Grazie. – Cris

+1

Le query con nome possono essere utilizzate per risolvere il problema del nome della proprietà: possono essere verificate facilmente in un test di unità. La query di runtime era solo per ridurre l'esempio - le query denominate dovrebbero sempre essere utilizzate. –

Problemi correlati