2011-01-27 2 views
5

structure de l'objet est comme ceRécupérer une structure graphique dans Hibernate

  • facture
    • client
    • Date de
    • Nombre
    • a beaucoup productlines (produit, quantité, prix)
    • a de nombreux ServiceLines (service, quantité, prix)
    • a beaucoup PaymentOptions (PaymentType (chèque, réception, etc.), Date, Somme)

Si je dois récupérer une liste des factures pour une période donnée avec Hibernate est très facile à faire avec paresseux chargement sans écrire de code appelez simplement get ... MAIS il y a l'inconvénient de trop d'appels DB, donc dans un environnement multi-utilisateur cette solution n'est pas correcte.

Avec JDBC simple, j'ai résolu cela en utilisant 3 requêtes: 3 jointures entre Invoice et ProductLines, Invoice et ServiceLines et Invoice and Payment Options. Après cela, j'ai construit l'objet dans la mémoire. Même chose peut être fait avec Hibernate Je sais MAIS ma question est qu'il n'existe pas de graphique de charge ou alors je peux passer une liste de factures et en nombre minimum d'appels (optimal) pour récupérer les données?

Répondre

4

Vous pouvez utiliser des requêtes avec join pour obtenir l'ensemble graphique d'objets en mémoire:

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

Oui c'est résoudre le problème dans une requête.Le seul inconvénient est le produit cartésien de toutes ces tables peut être énorme non? – Cris

+1

En effet. Cependant, avec cette méthode, vous pouvez toujours choisir quelles associations chercher immédiatement et lesquelles charger paresseusement.Ensuite, vous pouvez utiliser la taille de lot, comme Simon l'a suggéré, pour accélérer les récupérations pour les fainéants. –

+1

+1 pour l'exemple, que j'ai ajouté à ma réponse. –

4

Vous voudrez peut-être considérer batch fetching pour vos lignes de facture et aller chercher impatiemment plusieurs associations telles que le client. Cela n'aboutira pas à un appel DB, mais si vous ajustez vos tailles de lots pour dépasser légèrement le nombre moyen de lignes de chaque type dans une facture, vous pouvez réduire à un par type de ligne.

Vous pouvez également requête en utilisant JPQL/HQL et explicitement fetch-rejoindre les lignes (as Russ decribes), mais vous obtenez un résultat plus établi que vous le feriez avec une approche aller chercher lot:

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 
} 

Si la taille les données brutes transférées s'avèrent être trop élevées, vous pouvez désactiver explicitement la récupération en supprimant "fetch" de la requête dans les endroits appropriés. Notez qu'il existe un problème de maintenance à l'aide de JPQL car le compilateur ne peut pas vérifier tous les noms de propriété pour vous, et si l'extraction est désactivée pour toutes les associations, la requête est un coût net. Vous pouvez commencer avec la récupération par lots si les performances ne sont pas un problème immédiat.

+0

vous me mettez dans la bonne direction (unfortunatelly je ne peux pas vous donner un up vote car je ne suis pas autorisé encore). Merci – Cris

+1

Des requêtes nommées peuvent être utilisées pour résoudre le problème de nom de propriété - elles peuvent être vérifiées facilement dans un test unitaire. La requête d'exécution consistait simplement à réduire l'exemple - les requêtes nommées doivent toujours être utilisées. –

Questions connexes