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

JPA Java Discussion :

[MANYTOMANY] Problème de jointure JPQL


Sujet :

JPA Java

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 38
    Par défaut [MANYTOMANY] Problème de jointure JPQL
    Bonjour,

    Je bloque actuellement sur des questions sur l'architecture logicielle liée aux EJB via JPA et je me heurte à un problème insoluble avec mes connaissances et les renseignements que j'ai pu glaner (en général des exemples simples et de type Many To One).

    Pour faire simple, on va considérer une bdd simple :

    [classe âge] ---- [classe âge/élève] ---- [élève] ---- [école]

    L'idée c'est que j'aimerai compter le nombre d'élève de chaque classe d'âge pour une école donnée. Déjà première interrogation sur l'architecture logiciel des EJB : dans le cas où j'ai actuellement fait un stateless pour chaque entity afin de fournir les services d'accès aux données correspondant à chaque table, faut il que j'intègre cette requête dans un des stateless dont les tables sont concernées (et laquelle) ? ou dans un nouveau stateless qui serait détaché d'un entity en particulier ?

    Deuxième interrogation c'est concernant le JPQL : sachant que je veux récupérer un nombre et un "libellé" <classe âge>, quelle sera la sortie de la requête car je pourrais récuperer les données sous forme de liste mais sachant qu'il y a plusieurs champs ...
    De plus sachant que jusque là j'ai vu que les jointures se faisaient en donnant le champ de clé étrangère au lieu de donner les tables concernées par la jointure (comme en SQL), faut il partir de l'entité [classe âge/élève] ?

    Merci d'avance pour vos réponses

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    2 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 938
    Par défaut
    Bonjour,
    Tout d'abord, sans vouloir casser ton architecture je ne pense pas que ce soit une super idée d'associer à chaque entité un stateless, imagine qu'il y'ait 100 tables dans ton projet tu feras 100 stateless ???? pour ma part tu peux créer les stateless par affinité de services offerts, par exemple un stateless pour gérer tous les services demandés par un utilisateur, par un administrateur, de statistique etc... par exemple j'ai un seul stateless générique qui repond à toutes mes requetes dans un des projets.
    Pour ta 2ieme question, je ne vois pas où il est ton pb, tu peux très cumuler dans une même sortie de requete des colonnes venant de tables differentes, en recupération tu feras des cast avec la bonne classe.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 38
    Par défaut
    Sachant que je n'ai pas trouvé grand chose sur les "bonnes pratiques" de la programmation EJB, j'ai tenté avec un stateless par entity pour rester dans un modèle objet type attribut/methodes avec entity/stateless (avec une 30ene de tables, c'est déjà assez lourd ).
    Concernant la requête, j'imagine que dans la liste de sortie, les données sont alternées ? C'était pour ça la question car t'as une liste avec GetResultList donc les données doivent surement être alternées dans la liste de retour.

    Sinon si t'as un lien vers une doc sur l'architecture logiciel autour des EJB et la façon dont on doit coder ce genre de projet je suis preneur !

  4. #4
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    2 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 2 938
    Par défaut
    GetResultList te retourne bien evidemment une collection d'Object, charge à toi lors de la recupération de caster pour recuperer les bons types.
    Je suis degouté,j'avais un lien de reference des EJB, ce site n'est plus dispo, je sais pas s'ils ont changé d'adresse, voila leur lien lien1, s'ils ont changé d'adresse qcq peut il me fournir la nouvelle?
    sinon regarde un peu celui ci==> lien2.
    Si t'as d'autres questions n'hesites pas.

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 38
    Par défaut
    Bonjour,

    J'avais déjà repéré ce site et j'ai pu y trouver quelques informations utiles. Par contre je me retrouve toujours avec mon problème de jointure Many-to-many. Ayant vu que les jointures entre table en jpql se font en "remontant" les clés étrangères ("select t table t left join t.foreignkey"), le problème du many to many est qu'on ne peut partir d'une des 2 tables "extérieur" à la relation n,m a priori vu qu'elles ne possèdent pas de clé étrangère (si on s'en tient aux 3 tables initiales).
    La seule solution que j'ai pu trouver est de faire un "select a table1 a,table2 b, table3 c" mais sachant que ça me crée un produit cartésien, il faut beaucoup de contrainte pour une simple requête.

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2007
    Messages : 149
    Par défaut
    hum ca t'irait pas un truc comme ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    select C from classeAge C
              fetch join C.listEleve E
              fetch join E.ecole S
              where S.libelle=:libelle
    Ensuite tu fais un

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    For (ClassAge classAge : listClassAge)
              log.debug("libelle : "+classAge.getLibelle()+" - nb eleve : "+classAge.getListEleve().size();

    (désolé si j'ai compris de travers ^^)

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 38
    Par défaut
    Bonjour,

    Alors j'ai peut être raté un gros détail mais là avec ton C.listEleve, tu considères que classeAge a un lien direct avec Eleve qui se traduit par un attribut listEleve. Dans le cas que je décris, l'entity ClasseAge ne possède aucune référence à élève et cette référence n'est présente que dans l'entity ClasseAge/Eleve par une classe primary key possédant la clé étrangère de ClasseAge et de Eleve.

    Donc soit j'ai vraiment raté un chapitre sur la manipulation et l'utilisation du JPQL (ce qui est largement possible), soit il y a un problème sur ce que tu as écris ^^

  8. #8
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2007
    Messages : 149
    Par défaut
    Euh tout dépend de ton entity de jointure. J'avais compris que tu avais fait un many to many et non deux many to one.

    [classe âge] ---- [classe âge/élève] ---- [élève]

    Si ton entity classe age/eleve ne joue le role que de jointure, map directement ton entity age en many to many avec eleve.

    Sinon meme si tu concerves ton enity de jointure, ca n'empeche pas de construire la requete il te faut une jointure de plus voila tout.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    for (ClassAge classAge : listClassAge)         
    {
              int nbEleves=0;
              for (ClassAgeEleve classAgeEleve : classAge.getListeClassAgeEleve)
                       nbEleves+=classAgeEleve .getListeEleve().size();
              log.debug("libelle : "+classAge.getLibelle() + " - nb eleve : "+nbEleves);
    }
    Oubli pas de fetch tes listes dans la requete

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 38
    Par défaut
    Pour eclaircir les choses, je vais montrer à quoi ressemble les classes :

    On a une classe :
    - ClasseAge avec un idClasseAge
    - Eleve avec un idEleve
    - ClasseAge/Eleve avec un id de type ClasseAge/ElevePK
    - ClasseAge/ElevePK avec comme attributs idEleve et idClasseAge


    Moi je prend ca pour un ManyToMany parce qu'on est en présente d'une relation n,m. Après je me trompe peut être dans les termes (j'ai vraiment l'impression de rien connaitre au SQL et aux bdd depuis que je touche au JPQL ..).

    Donc on est bien en présence d'une classe "intermédiaire" ClassAge/Eleve qui contient un attribut id généré par la persistence qui est de type "pk" contenant un attribut correspondant à chaque clé étrangère.

    J'espère que c'est plus clair comme ça et désolé si j'ai créé une confusion !

    Dans tous les cas le count n'est pas vraiment le centre du problème. Mon problème est plutôt la difficulté de faire une multiple jointure qui traverse une association n,m. Comme je le disais au départ, j'ai surtout trouvé des cas de type n,1 où la jointure utilisait la clé étrangère sans même nommer la seconde table de la jointure...

    Je vais voir ta solution de mapper la relation age/eleve mais la création de l'entity age/classe m'a été proposé lors de la génération des entities.

  10. #10
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2007
    Messages : 149
    Par défaut
    Si tu veux garder ta table de jointure ceci devrait marcher non ? :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
     
    select C from classeAge C
              fetch join C.listClassAgeEleve AE
              fetch join AE.eleve E
              fetch join E.ecole S
              where S.libelle=:libelle

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 38
    Par défaut
    Citation Envoyé par Delwyn Voir le message

    fetch join C.listClassAgeEleve AE
    J'essai de comprendre la logique de ta requête mais cette partie me turlupine : listClassAgeEleve semble être un élément de ClasseAge selon ta requête mais nullepart ce lien existe vu que la relation entre ClasseAge et Eleve apparait uniquement dans la table classeage/eleve donc l'entity classeage/eleve.
    Désolé pour tout ce trifouillage mais une fois que j'aurai compris ce concept je serais enfin débloqué ^^

  12. #12
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2007
    Messages : 149
    Par défaut
    Tu devrais mapper en bidirectionnel, c'est a dire rajouter la relation qu'il te manque, avec un mappedby

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 38
    Par défaut
    Cela aurait pu être une solution mais mon cas réel , étant plus compliqué que mon cas d'exemple simpliste, présente un attribut dans la table intermédiaire donc je doute que ça soit possible de faire ça dans mon cas.

  14. #14
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2007
    Messages : 149
    Par défaut
    Garde ton entity de jointure (si tu as un attribut spécifique tu n'as pas d'autre choix) mais fait un mapping bidirectionnel.

  15. #15
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 38
    Par défaut
    Bonjour,

    Tu pourrais expliciter un peu ce que tu penses que je devrais faire ? Je n'ai encore jamais fait de mapping bidirectionnel dans ce cas donc si je dois prendre en compte l'entity de jointure dans ce mapping ou je fais un manytomany entre les 2 tables classesAge et Eleve ?

    Merci d'avance ^^

  16. #16
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2007
    Messages : 149
    Par défaut
    Donne nous le code de ton mapping existant ce sera plus simple

  17. #17
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 38
    Par défaut
    Alors le principe reste le même mais pour des "éléments" de contrats :

    Contractualisation - EtatdecontractualisationHasContractualisation - Etatdecontractualisation


    Contractualisation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    @Entity
    @Table(name="contractualisation")
    public class Contractualisation implements Serializable {
    	private static final long serialVersionUID = 1L;
     
    	@Id
    	@GeneratedValue(strategy=GenerationType.AUTO)
    	@Column(unique=true, nullable=false)
    	private int idcontractualisation;
    EtatdecontractualisationHasContractualisation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    @Entity
    @Table(name="etatdecontractualisation_has_contractualisation")
    public class EtatdecontractualisationHasContractualisation implements Serializable {
    	@EmbeddedId
    	private EtatdecontractualisationHasContractualisationPK pk;
     
    	private byte statut;
     
    	private static final long serialVersionUID = 1L;
    Etatdecontractualisation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    @Entity
    @Table(name="etatdecontractualisation")
    public class Etatdecontractualisation implements Serializable {
    	private static final long serialVersionUID = 1L;
     
    	@Id
    	@GeneratedValue(strategy=GenerationType.AUTO)
    	@Column(unique=true, nullable=false)
    	private int idetatdecontractualisation;
    Et la classe de l'id de l'entity jointure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    @Embeddable
    public class EtatdecontractualisationHasContractualisationPK implements Serializable {
    	@Column(name="etatdecontractualisation_idetatdecontractualisation")
    	private int etatdecontractualisationIdetatdecontractualisation;
     
    	@Column(name="contractualisation_idcontractualisation")
    	private int contractualisationIdcontractualisation;
     
    	private static final long serialVersionUID = 1L;

  18. #18
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2007
    Messages : 149
    Par défaut
    Ton maping est étrange, tu ne lies pas tes entity entre elles :

    Contractualisation - EtatdecontractualisationHasContractualisation - Etatdecontractualisation

    tu devrais avoir un truc comme ca (rapidement)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    @Entity
    @Table(name="contractualisation")
    public class Contractualisation implements Serializable {
    	private static final long serialVersionUID = 1L;
     
    	@Id
    	@GeneratedValue(strategy=GenerationType.AUTO)
    	@Column(unique=true, nullable=false)
    	private int idcontractualisation;
     
    	@OneToMany(fetch ...)
    	@JoinColumn
    	private EtatdecontractualisationHasContractualisation  etatdecontractualisationHasContractualisation;
     
    	//getter setter
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    @Entity
    @Table(name="etatdecontractualisation_has_contractualisation")
    public class EtatdecontractualisationHasContractualisation implements Serializable {
    	@EmbeddedId
    	private EtatdecontractualisationHasContractualisationPK pk;
     
    	private byte statut;
     
    	private static final long serialVersionUID = 1L;
     
    	@ManyToOne(mappedBy...)
    	private List<Contractualisation> listContractualisation;
     
    	@ManyToOne(mappedBy...)
    	private List<Etatdecontractualisation> listEtatdecontractualisation ;
     
    	//getter setter
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    @Entity
    @Table(name="etatdecontractualisation")
    public class Etatdecontractualisation implements Serializable {
    	private static final long serialVersionUID = 1L;
     
    	@Id
    	@GeneratedValue(strategy=GenerationType.AUTO)
    	@Column(unique=true, nullable=false)
    	private int idetatdecontractualisation;
     
    	@OneToMany(fetch ...)
    	@JoinColumn
    	private EtatdecontractualisationHasContractualisation  etatdecontractualisationHasContractualisation;
     
    	//getter setter
    Je te propose le tut suivant qui est très bien fait :
    http://tahe.developpez.com/java/jpa/

  19. #19
    Membre averti
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    38
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 38
    Par défaut
    J'ai rajouté ce que tu as fait mais dans le "sens contraire", c'est à dire que les list sont dans les entities contractualisation et etatdecontractualisation et les attributs "simples" dans l'entity de jointure comme le montre le tuto dont tu m'as envoyé le lien.
    Je vais voir comment je vais pouvoir utiliser ces modifs dans le mapping pour pouvoir avoir le résultat que je cherche.

    Merci pour ton aide en tout cas !

  20. #20
    Membre expérimenté
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    149
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Janvier 2007
    Messages : 149
    Par défaut
    A oui effectivement j'ai inversé le mapping, bien vu ^^

Discussions similaires

  1. Problème de jointure de tables
    Par AurelBUD dans le forum Langage SQL
    Réponses: 6
    Dernier message: 20/04/2005, 17h27
  2. Probléme de jointure
    Par Ajrarn dans le forum Langage SQL
    Réponses: 14
    Dernier message: 24/02/2005, 15h57
  3. Vraisemblable problème de jointure
    Par pimousse76 dans le forum Langage SQL
    Réponses: 3
    Dernier message: 23/02/2005, 16h34
  4. [MS Access] Problème de jointure
    Par Erakis dans le forum Langage SQL
    Réponses: 3
    Dernier message: 07/02/2005, 22h15
  5. Problème de jointure ?!
    Par ebaynaud dans le forum Langage SQL
    Réponses: 8
    Dernier message: 03/11/2004, 12h27

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