IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Hibernate Java Discussion :

Traduction SQL multiplie les joins [HQL]


Sujet :

Hibernate Java

  1. #1
    Membre éprouvé Avatar de leminipouce
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    janvier 2004
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : janvier 2004
    Messages : 754
    Points : 1 287
    Points
    1 287
    Par défaut Traduction SQL multiplie les joins
    Bonjour,

    Nous venons de faire une migration de Hibernate 3.2.5 (GA) vers Hibernate 3.6.7 (Final).
    Après avoir mis à jour nos dialect (on était sur une BDD Sybase 12.5 avec SybaseDialect et on est passé sur une BDD Sybase ASE 15 avec donc le dialecte SybaseASE15Dialect) et 2-3 dépendances Maven (slf4j-log12,...) tout (ou presque) semble fonctionner.

    En fait on s'est rendu compte, sur une requête initialement énorme, que cette nouvelle version d'Hibernate duplique certaines jointures (inner join dans notre cas) ce qui peut amener à exploser les limites de 50 tables/vues maxi dans une seule requête (limite dans les spécs de Sybase)

    Sans parler de la requête initiale qui pourrait certainement être revue et améliorée, de manière générale nous avons plus de jointures sur les requête, donc des temps de réponse plus long !

    Ci-dessous un exemple pour illustrer.
    Point de vue relationnel : Un Agriculteur ne peut avoir qu'un seul EtatAgriculteur (relation many-to-one) et peut avoir 'n' Parcelle. Une Parcelle ne peut appartenir qu'à un Agriculteur. Relation depuis l'agriculteur en one-to-many.
    La requête complètement bidonnée ci-dessous cherche à récupérer les Parcelle, en y associant les Agriculteur et leur EtatAgriculteur.

    J'ai récupéré avec P6Spy le résultat de la traduction SQL faite par Hibernate.

    Requête HQL initiale :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    from Parcelle p inner join p.agriculteur as agri inner join p.agriculteur.etatAgriculteur as etat  where (p.agriculteur.agrCdn = agri.agrCdn and agri.etatAgriculteur.etatCdn = etat.etatCdn)
    Traduction SQL faite par Hibernate 3.2.5.GA
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select parcelle0_.PAR_CDN as PAR1_36_0_, agriculteu1_.AGR_CDN as AGR1_27_1_, etatagricu3_.ETAT_CDN as ETAT1_33_2_, parcelle0_.PAR_LIB_LB as PAR2_36_0_, parcelle0_.PAR_SURFACE_INT as PAR3_36_0_, parcelle0_.PAR_CADAST_LB as PAR4_36_0_, parcelle0_.AGR_CDN as AGR5_36_0_, agriculteu1_.AGR_NOM_LB as AGR2_27_1_, agriculteu1_.AGR_PRENOM_LB as AGR3_27_1_, agriculteu1_.AGR_ADR1_LB as AGR4_27_1_, agriculteu1_.AGR_ADR2_LB as AGR5_27_1_, agriculteu1_.AGR_ACTIF_ON as AGR6_27_1_, agriculteu1_.AGR_CODPOS_LB as AGR7_27_1_, agriculteu1_.TYPE_CDN as TYPE8_27_1_, agriculteu1_.ETAT_CDN as ETAT9_27_1_, agriculteu1_.AGR_PERE_CDN as AGR10_27_1_, agriculteu1_.COM_CP_RFA as COM11_27_1_, agriculteu1_.COM_INSEE_RFA as COM12_27_1_, agriculteu1_.JUR_CDN as JUR13_27_1_, etatagricu3_.ETAT_LIB_LB as ETAT2_33_2_, etatagricu3_.ETA_RFA as ETA3_33_2_ 
    from PARCELLE parcelle0_ 
    inner join AGRICULTEUR agriculteu1_ on parcelle0_.AGR_CDN=agriculteu1_.AGR_CDN 
    inner join ETAT_AGRICULTEUR etatagricu3_ on agriculteu1_.ETAT_CDN=etatagricu3_.ETAT_CDN 
    where parcelle0_.AGR_CDN=agriculteu1_.AGR_CDN and agriculteu1_.ETAT_CDN=etatagricu3_.ETAT_CDN
    Traduction SQL faite par Hibernate 3.6.7.Final :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    select parcelle0_.PAR_CDN as PAR1_36_0_, agriculteu1_.AGR_CDN as AGR1_27_1_, etatagricu3_.ETAT_CDN as ETAT1_33_2_, parcelle0_.PAR_LIB_LB as PAR2_36_0_, parcelle0_.PAR_SURFACE_INT as PAR3_36_0_, parcelle0_.PAR_CADAST_LB as PAR4_36_0_, parcelle0_.AGR_CDN as AGR5_36_0_, agriculteu1_.AGR_NOM_LB as AGR2_27_1_, agriculteu1_.AGR_PRENOM_LB as AGR3_27_1_, agriculteu1_.AGR_ADR1_LB as AGR4_27_1_, agriculteu1_.AGR_ADR2_LB as AGR5_27_1_, agriculteu1_.AGR_ACTIF_ON as AGR6_27_1_, agriculteu1_.AGR_CODPOS_LB as AGR7_27_1_, agriculteu1_.TYPE_CDN as TYPE8_27_1_, agriculteu1_.ETAT_CDN as ETAT9_27_1_, agriculteu1_.AGR_PERE_CDN as AGR10_27_1_, agriculteu1_.COM_CP_RFA as COM11_27_1_, agriculteu1_.COM_INSEE_RFA as COM12_27_1_, agriculteu1_.JUR_CDN as JUR13_27_1_, etatagricu3_.ETAT_LIB_LB as ETAT2_33_2_, etatagricu3_.ETA_RFA as ETA3_33_2_ 
    from PARCELLE parcelle0_ 
    inner join AGRICULTEUR agriculteu1_ on parcelle0_.AGR_CDN=agriculteu1_.AGR_CDN 
    inner join AGRICULTEUR agriculteu2_ on parcelle0_.AGR_CDN=agriculteu2_.AGR_CDN 
    inner join ETAT_AGRICULTEUR etatagricu3_ on agriculteu2_.ETAT_CDN=etatagricu3_.ETAT_CDN 
    where parcelle0_.AGR_CDN=agriculteu1_.AGR_CDN and agriculteu1_.ETAT_CDN=etatagricu3_.ETAT_CDN
    Est-ce que quelqu'un saurait m'expliquer pourquoi il y a un inner join de plus avec Hbn3.6.7 et comment y remédier ?

    Merci,
    Pouce.
    Si , et la ont échoué mais pas nous, pensez à dire et cliquez sur . Merci !

    Ici, c'est un forum, pas une foire. Il y a de respectables règles... à respecter !

  2. #2
    Expert confirmé
    Profil pro
    Inscrit en
    août 2006
    Messages
    3 271
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : août 2006
    Messages : 3 271
    Points : 4 112
    Points
    4 112
    Par défaut
    Je dirais que le problème vient de ta requête HQL où il y a déjà une double jointure, une par inner join, une dans le where.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    from Parcelle p inner join p.agriculteur as agri inner join agri.etatAgriculteur as etat)
    Ce n'est pas suffisant ?

  3. #3
    Membre éprouvé Avatar de leminipouce
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    janvier 2004
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : janvier 2004
    Messages : 754
    Points : 1 287
    Points
    1 287
    Par défaut
    Je suis bien d'accord sur le fait, la requête est pourrie pas super.

    Mais ce n'est pas moi qui l'ai écrite (pour être tout à fait précis on fournit un framework qui embarque hibernate et qui est utilisé par plus d'une 50aine de projets. C'est le projet pilote qui remonte cette erreur.)

    La requête que je donne en exemple est bidonnée, juste pour reproduire le cas. On ne peut décemment pas ré-écrire toutes les requêtes et dans certains cas ces clauses where se justifient. (ré-écrire toutes les requêtes demanderait un travail titannesque qui serait killer pour la mise en prod de notre évole... même si c'est la solution le plus intelligente !)

    Le véritable problème réside dans le fait qu'Hibernate 3.2.5 ne faisait que 2 jointures là où, pour la même requête, Hibernate 3.6.7 en fait 3. (et quand cette jointure porte sur une vue qui elle même est déjà énorme avec pleins de sous-jointure, etc... Sybase considère que toutes les sous-jointures sont en double, les compte donc 2 fois dans le nombre maxi de tables accédées... et explose le quota de 50 !)
    Si , et la ont échoué mais pas nous, pensez à dire et cliquez sur . Merci !

    Ici, c'est un forum, pas une foire. Il y a de respectables règles... à respecter !

  4. #4
    Expert confirmé
    Profil pro
    Inscrit en
    août 2006
    Messages
    3 271
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : août 2006
    Messages : 3 271
    Points : 4 112
    Points
    4 112
    Par défaut
    J'ai bien une liste de propositions, mais je pense qu'aucune ne te satisfera :
    - ne pas faire la migration vers la nouvelle version d'Hibernate
    - ouvrir un bug/demande d'évolution pour ce problème
    - proposer toi même le correctif
    - réécrire la ou les requêtes

    Tu as vraiment besoin de migrer vers une nouvelle version d'Hibernate ?

  5. #5
    Membre éprouvé Avatar de leminipouce
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    janvier 2004
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : janvier 2004
    Messages : 754
    Points : 1 287
    Points
    1 287
    Par défaut
    Héhé


    • Tu as raison, la première me sastifait pas tellement. Je suis prestataire et cette migration fait parti de ma mission. J'avoue un peu honteux, que je n'ai pas demandé ce qui avait poussé à vouloir cette migration Hibernate. C'est l'architecte chef qui a poussé ça...


    • Pour ce qui est du ticket chez Hibernate, j'ai déjà commencé par poser la même question sur leur forum. Et pour l'instant j'ai pas tellement de succès. Viendra après la soumission d'un bug/demande d'évole. S'ils me disent que c'est corrigé dans la toute fraîche 4.0 il va falloir que je sois très convainquant chez mon client
    • Pour faire le correctif, j'y ai pensé. Mais ça demande du temps, donc de l'argent... et je suis pas sûr que mon client est envie de payer pour ça. Peut-être sur mon temps libre le soir, mais j'ai pas tellement de BDD Sybase chez moi A tester peut-être déjà avec une Postgre par exemple... Reste à me libérer du temps.
    • Ré-écrire toutes les requêtes est exclu d'office. Trop cher. Pas finançable par notre équipe. Pas acceptable par nos "clients internes".

    Merci en tout cas pour les propositions. Ca veut aussi dire que selon toi ce n'est pas solvable en terme de configuration Hibernate ?
    Si , et la ont échoué mais pas nous, pensez à dire et cliquez sur . Merci !

    Ici, c'est un forum, pas une foire. Il y a de respectables règles... à respecter !

  6. #6
    Expert confirmé
    Profil pro
    Inscrit en
    août 2006
    Messages
    3 271
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : août 2006
    Messages : 3 271
    Points : 4 112
    Points
    4 112
    Par défaut
    Et en changeant le dialect ?
    N'y a t il pas un dialect commun à tous les Sybase ?

    Pour moi, le plus simple serait de remettre en cause la migration (si tu ne trouves pas rapidement une autre solution via les forums), surtout si elle n'est pas justifiée pour de vraies raisons: correction de bugs gênants chez vous, performances, etc...

  7. #7
    Membre éprouvé Avatar de leminipouce
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    janvier 2004
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : janvier 2004
    Messages : 754
    Points : 1 287
    Points
    1 287
    Par défaut
    Pour ce qui est du Dialect, je suis obligé de monté. Sinon ça ne marche pas avec la nouvelle version d'ASE.

    Pour ce qui est de la clause where, en fait elle n'y ait pour rien. Je viens de la virer dans ma requête HQL, et j'ai toujours la même sortie SQL (au delta près évidemment du where...)

    Requête HQL :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    from Parcelle p inner join p.agriculteur as agri inner join p.agriculteur.etatAgriculteur as etat
    Traduction par Hibernate 3.6.7 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    select parcelle0_.PAR_CDN as PAR1_36_0_, agriculteu1_.AGR_CDN as AGR1_27_1_, etatagricu3_.ETAT_CDN as ETAT1_33_2_, parcelle0_.PAR_LIB_LB as PAR2_36_0_, parcelle0_.PAR_SURFACE_INT as PAR3_36_0_, parcelle0_.PAR_CADAST_LB as PAR4_36_0_, parcelle0_.AGR_CDN as AGR5_36_0_, agriculteu1_.AGR_NOM_LB as AGR2_27_1_, agriculteu1_.AGR_PRENOM_LB as AGR3_27_1_, agriculteu1_.AGR_ADR1_LB as AGR4_27_1_, agriculteu1_.AGR_ADR2_LB as AGR5_27_1_, agriculteu1_.AGR_ACTIF_ON as AGR6_27_1_, agriculteu1_.AGR_CODPOS_LB as AGR7_27_1_, agriculteu1_.TYPE_CDN as TYPE8_27_1_, agriculteu1_.ETAT_CDN as ETAT9_27_1_, agriculteu1_.AGR_PERE_CDN as AGR10_27_1_, agriculteu1_.COM_CP_RFA as COM11_27_1_, agriculteu1_.COM_INSEE_RFA as COM12_27_1_, agriculteu1_.JUR_CDN as JUR13_27_1_, etatagricu3_.ETAT_LIB_LB as ETAT2_33_2_, etatagricu3_.ETA_RFA as ETA3_33_2_ 
    from PARCELLE parcelle0_ 
    inner join AGRICULTEUR agriculteu1_ on parcelle0_.AGR_CDN=agriculteu1_.AGR_CDN 
    inner join AGRICULTEUR agriculteu2_ on parcelle0_.AGR_CDN=agriculteu2_.AGR_CDN
    inner join ETAT_AGRICULTEUR etatagricu3_ on agriculteu2_.ETAT_CDN=etatagricu3_.ETAT_CDN
    Bon... on a éliminé la cause de la requête... c'est déjà ça
    Si , et la ont échoué mais pas nous, pensez à dire et cliquez sur . Merci !

    Ici, c'est un forum, pas une foire. Il y a de respectables règles... à respecter !

  8. #8
    Membre chevronné
    Inscrit en
    août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Non mais par contre ta requête devrait s'écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    from Parcelle p 
          inner join p.agriculteur as agri 
          inner join agri.etatAgriculteur as etat
    Ça ne me semble pas illogique qu'il y ait double jointure, vu que l'objet "p.agriculteur" est mentionné de deux façons différentes : d'abord on lui donne un alias, et ensuite on ne s'en sert pas.

  9. #9
    Membre éprouvé Avatar de leminipouce
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    janvier 2004
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : janvier 2004
    Messages : 754
    Points : 1 287
    Points
    1 287
    Par défaut
    Citation Envoyé par Rei Ichido Voir le message
    Ça ne me semble pas illogique qu'il y ait double jointure, vu que l'objet "p.agriculteur" est mentionné de deux façons différentes : d'abord on lui donne un alias, et ensuite on ne s'en sert pas.
    Tu as tout à fait raison. Et c'est bien là que le bas blesse.

    Il y avait un bug sous Hibernate, corrigé dès la version 3.3, ou Hibernate réutilisait les alias sur ce genre de jointure. La logique veut qu'il ne le fasse pas. Et la correction a été apportée dans ce sens. https://hibernate.onjira.com/browse/HHH-4091

    En gros, si tu déclares A.B as b, tu ne dois plus jamais utiliser A.B.xxx mais b.xxx (à moins de vouloir faire explicitement une nouvelle jointure) --c'est bel et bien la notion de jointure explicite vs jointure implicite qui est en cause ici. Et ceci est valable aussi bien dans les jointures (inner, full, left outer, ...) que dans les clauses WHERE et ORDER BY.

    Bref, il faut en effet dire à tous les projet que s'ils ont exploité un bug d'Hibernate 3.2.5 et en ont profité pour écrire des requêtes cradso... ils ont juste accumulé de la dette technique (Livre blanc : Maitrisez votre dette technique) qu'il faut désormais payer

    En tout cas merci beaucoup de vous être intéressé à mon sujet et m'avoir consacré du temps.

    Pouce.
    Si , et la ont échoué mais pas nous, pensez à dire et cliquez sur . Merci !

    Ici, c'est un forum, pas une foire. Il y a de respectables règles... à respecter !

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 15/05/2008, 12h48
  2. Multiplier les And dans Sql Insert Into
    Par samlepiratepaddy dans le forum Requêtes et SQL.
    Réponses: 17
    Dernier message: 23/09/2005, 22h55
  3. Génération de script SQL avec les données
    Par borgfabr dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 05/03/2004, 14h57
  4. Réponses: 3
    Dernier message: 28/11/2003, 22h26
  5. [ODBC] erreur SQL pour les unions qui renvoient vide
    Par fabriceMerc dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 25/11/2003, 12h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo