2010-03-16 3 views
5

Dans les projets où Hibernate est mon fournisseur de persistance, je peux émettre des requêtes avec des expressions 'join fetch', et Hibernate va générer un SQL qui reflète: SQL contenant des expressions de jointure utilisant des chemins de comparaison valides. Cependant, EclipseLink émet des instructions SQL avec des plans cartésiens laids, ce qui nuit gravement aux performances. En lisant ce article, il mentionne que la recherche ardente pourrait générer des plans cartésiens, mais il oublie commodément que d'autres fournisseurs (Hibernate) peuvent optimiser cela.EclipseLink génère un plan cartésien au lieu de jointures (internes) dans SQL. Pourquoi?

Alors, est-il possible de demander à EclipseLink d'optimiser ces requêtes? Je crois que peu de relations peuvent être optimisées grâce à l'utilisation de l'annotation @FetchJoin, mais j'espère trouver quelque chose qui n'inclut pas la diffusion d'annotations spécifiques à ORM sur le modèle de domaine.

À titre d'exemple, voici une requête (dynamique) que je lance comme JPQL:

String query = "select w from WorkOrder w " + 
      "inner join fetch w.type " + 
      "inner join fetch w.details " + 
      "inner join fetch w.project " + 
      "inner join fetch w.priority " + 
      "inner join fetch w.networkElement "; 

Et voici la sortie EclipseLink:

SELECT t1.ID, t1.CREATION, ... (the fetch fields here) 
FROM swa_network_element t5, swa_priorities t4, swa_dispatch_project t3, swa_work_order_detail t2, swa_work_orders t1, swa_work_order_type t0 
WHERE ((t1.alpha_id LIKE '%TSK%') AND (((((t0.ID = t1.TYPE_ID) AND (t2.worder_id = t1.ID)) AND (t3.id = t1.project_id)) AND (t4.ID = t1.priority_id)) AND (t5.ID = t1.ne_id))) ORDER BY t1.CREATION DESC 

Meilleures salutations, Rodrigo Hartmann

+0

Essayé affichage sur les forums EclipseLink, mais n'a obtenu aucune réponse là aussi. Sujet délicat? – javabeats

+0

Trouvé votre question creusant dans le même problème. Hacking dessus aujourd'hui, postera si je trouve quelque chose. – Freiheit

+0

Mon DBA m'a dit que si EclipseLink rejoignait les tables sur la clause WHERE, en ce qui concerne $ QL $ erver, cela n'aurait aucun impact particulier sur les performances de la requête. J'ai vu ses tests, et j'étais satisfait des résultats. Le seul problème restant est maintenant quand EclipseLink ajoute la même table * deux fois * sans raison valable. Pour ces requêtes particulières, j'ai dû utiliser des critères pour obtenir un résultat satisfaisant. Parfois, comme ça, Hibernate me manque. – javabeats

Répondre

3

Essayez d'utiliser:

@org.eclipse.persistence.annotations.JoinFetch(JoinFetchType.INNER)

- ou -

@org.eclipse.persistence.annotations.JoinFetch(JoinFetchType.OUTER)

Les jointures externes sont recommandées pour les colonnes nullable.

que j'ai trouvé plus d'informations dans ce blog: http://vard-lokkur.blogspot.com/2010/09/jpa-demystified-episode-1-onetomany-and.html

Cordialement,

Victor Tortorello Neto

+0

Voir également [un suivi] (http://vard-lokkur.blogspot.com/2010/12/jpa-insert-instead-of-update.html) sur ce blog: * utiliser '@JoinFetch (JoinFetchType.INNER) 'si et seulement si vous êtes absolument sûr, cette entité associée existera toujours - ex. lorsque le schéma de base de données ne permet pas d'autre possibilité. * – Arjan

0

Je ne suis pas sûr de ce que vous voulez dire? Le SQL semble correct, il y a une jointure pour chaque table, quelle table manque une jointure?

Quel est le code SQL attendu? Si vous voulez placer la condition de jointure dans la clause FROM au lieu de la clause WHERE, EclipseLink le fait pour les jointures externes, mais pas pour les jointures internes, car cela ne fait aucune différence de. Si vous le souhaitez, vous pouvez configurer EclipseLink 2.4 pour imprimer la condition de jointure pour les jointures internes dans la clause FROM à l'aide de l'API setPrintInnerJoinInWhereClause (false) de DatabasePlatform, mais cela ne devrait pas avoir d'impact sur la base de données. Le post de blog parlant de jonction de récupération de problèmes cartésiens est lorsque vous joignez plusieurs relations de 1 m, ce qui peut entraîner le retour d'un grand nombre de données. Il n'y a aucun moyen d'optimiser cela avec la récupération de jointure, car vous avez besoin de toutes les données. Dans EclipseLink, vous pouvez utiliser la récupération par lots, ce qui est beaucoup plus efficace que la récupération de jointure.

Voir, http://java-persistence-performance.blogspot.com/2010/08/batch-fetching-optimizing-object-graph.html

Questions connexes