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 :

Comment accéder aux propriétés de l'entité située de l'autre côté d'une @ManyToMany ?


Sujet :

Hibernate Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 818
    Billets dans le blog
    14
    Par défaut Comment accéder aux propriétés de l'entité située de l'autre côté d'une @ManyToMany ?
    Comme je n'obtiens pas de réponse satisfaisante à mes divers message expliquant en détail mon problème réel et comme je ne trouve pas non plus de réponse après des jours de recherche sur Internet, je pose ici le cas général qui me préoccupe.

    Soit le MCD suivant :
    A -0,n----Associer----0,n- B

    Dans le mapping, j'aurai deux entités A et B, chacune avec une propriété du type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Set<autreEntite> autreEntites = new HashSet<autreEntite>(0);
    et un @ManyToMany sur les getters et setters.

    Comment lire les propriétés de B en partant de A et vice-versa ?
    Autrement dit, à partir de cette requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Query q = entityManager.createQuery("FROM A WHERE condition");
    A a = (A) q.getSingleResult();
    Comment lire les propriétés de B correspondant à a ?

    J'ai essayé ceci :
    Mais dès cette ligne j'ai une erreur (à partit d'un user (A), je cherche à savoir s'il est inscrit à un stage (B) :
    16:26:14,740 INFO [Authenticator] authenticating - recherche session de stage
    16:26:14,742 DEBUG [EntityTransaction] marking JPA resource-local transaction for rollback
    16:26:14,743 WARN [SeamLoginModule] Error invoking login method
    javax.el.ELException: java.lang.NullPointerException
    at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:339)
    ...
    Caused by: java.lang.NullPointerException
    at org.domain.stamas.session.Authenticator.authenticate(Authenticator.java:76)
    ...
    La ligne 76 étant l'équivalent de celle du Set<B>.

    C'est un problème simple et courant non ?

    La requête SQL me prend 1 minute à écrire et en PHP je saurais la traiter je pense en moins d'un quart d'heure.

    Sur la planète Seam, j'y suis depuis des jours. Ça doit être la gravité qui est plus forte, on avance moins vite !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    J'ai pas tout compris.
    Le NullPointerException ne vient il pas simplement de ta requête qui ne te renvoie rien ?

    Pour accéder à tes objets B à partir de A, il faut effectivement faire un a.getBs().

    Quant aux requêtes, tu dois passer par une jointure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    from A a inner join a.bs b
    where a.proprieteDeA = ? and b.proprieteDeB = ?

  3. #3
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 818
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par fr1man Voir le message
    J'ai pas tout compris.
    Le NullPointerException ne vient il pas simplement de ta requête qui ne te renvoie rien ?
    La requête renvoie bien un résultat et l'étudiant qui se connecte est bel et bien inscrit à un stage dans la BDD.

    Pour accéder à tes objets B à partir de A, il faut effectivement faire un a.getBs().

    Quant aux requêtes, tu dois passer par une jointure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    from A a inner join a.bs b
    where a.proprieteDeA = ? and b.proprieteDeB = ?
    En l'occurrence, ce sera un LEFT JOIN puisque tous les étudiants ne sont pas inscrits à un stage.

    Tu veux dire que sans la jointure, je ne peux pas récupérer B ? A quoi sert le mapping @ManyToMany alors ? Seulement pour aliementer la table associative ?
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    La jointure sert à deux choses :
    - pouvoir poser des contraintes sur les attributs de B
    - pouvoir charger les éléments de B en utilisant le mot clef fetch sur ta jointure
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    from A a inner join FETCH a.bs b
    where a.proprieteDeA = ? and b.proprieteDeB = ?
    Si tu ne précises pas le fetch et que tu es en lazy loading, ta collection de B ne sera pas chargée. (d'où surement le nullPointerException)

  5. #5
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    non non non

    faut pas tous mélanger! fr1man

    Le join, sert bien à ce que tu dit, seulement dans le deuxième cas, on l'utilise uniquement quand on veux EXPLICITEMENT demander à hibernate de charger MAINTENANT la collection. Dans les autres cas, hibernate la chargera sur une requete séparée, au moment opportun. C'est suffisant dans 99% des cas d'utilisation

    cinephil: le @manytomany va demander à Hibernate de charger le Set automatiquement. On peux avoir le code EXACT à la ligne qui génère le nullpointerexception? (org.domain.stamas.session.Authenticator.authenticate(Authenticator.java:76)). C'est en général pas hibernate qui cause ça. Quand hibernate n'arrive pas à charger une collection reliée par un manytomany ou onetomany, il déclenche un LazyLoadingException, en général pour te dire que ta session est déjà fermée et qu'il est donc devenu impossible de charger la collection.

  6. #6
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    @ tchize_
    Merci mais je sais très bien comment fonction fetch et je ne mélange rien.

    Cependant, mea culpa pour le nullPointerExeption, on aurait effectivement plutôt un lazyLoadingException.

  7. #7
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 818
    Billets dans le blog
    14
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    On peux avoir le code EXACT à la ligne qui génère le nullpointerexception? (org.domain.stamas.session.Authenticator.authenticate(Authenticator.java:76)).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Set<TeSessionSsn> sessions = user.getThCandidatCnd().getTeSessionSsns();
    ThCandidatCnd hérite de ThUtilisateurUti.

    MCD :
    TeSessionSsn -0,n----Inscrire----0,n- ThCandidatCnd -1,1----Etre----0,1- ThUtilisateurUti

    Du coup j'ai essayé le LEFT JOIN dans la requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
                Query query = entityManager.createQuery(
                        "FROM ThUtilisateurUti u " +
                        "LEFT JOIN u.thCandidatCnd c " +
                        "LEFT JOIN u.TeSessionSsns s " +
                        "WHERE u.utiLogin = :username " +
                            "AND u.utiMotPasse = :password");
    Et j'obtiens cette erreur :
    javax.el.ELException: java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: thCandidatCnd of: org.domain.stamas.entity.ThUtilisateurUti [FROM org.domain.stamas.entity.ThUtilisateurUti u LEFT JOIN u.thCandidatCnd c LEFT JOIN u.TeSessionSsns s WHERE u.utiLogin = :username AND u.utiMotPasse = :password]
    Encore un problème de mapping ?
    Dans ThUtilisateurUti :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        private ThCandidatCnd thCandidatCnd;
     
        @Transient
        @OneToOne(fetch = FetchType.LAZY)
        @JoinColumn(name="cnd_id_utilisateur", referencedColumnName="uti_id_personne")
        public ThCandidatCnd getThCandidatCnd() {
            return this.thCandidatCnd;
        }
     
        public void setThCandidatCnd(ThCandidatCnd thCandidatCnd) {
            this.thCandidatCnd = thCandidatCnd;
        }
    Je me suis dit que peut-être il n'arrivait pas à écrire la condition de jointure car comme ThCandidatCnd hérite de ThUtilisateurUti qui hérite de TePersonnePrs, j'ai commenté les identifiants de ThCandidatCnd et de ThUtilisateurUti.

    Dans ThUtilisateurUti, au départ généré par Seam Generate Entities puis modifié suite à une autre discussion où on m'avait conseillé de virer les identifiants des entités filles :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
        //private int utiIdPersonne;
     
        /*@GenericGenerator(name = "genUtilisateur", strategy = "foreign", parameters = @Parameter(name = "property", value = "tePersonnePrs"))
        //@Id
        @GeneratedValue(generator = "genUtilisateur")
        //@Column(name = "uti_id_personne", unique = true, nullable = false)
        @Transient
        public int getUtiIdPersonne() {
            return this.utiIdPersonne;
        }
     
        public void setUtiIdPersonne(int utiIdPersonne) {
            this.utiIdPersonne = utiIdPersonne;
        }*/
    Bref, je suis toujours perdu dans les méandres d'Hibernate !
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

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

Discussions similaires

  1. Comment accéder aux propriétés d'un objet de la bibliothèque
    Par jpboogie dans le forum ActionScript 1 & ActionScript 2
    Réponses: 2
    Dernier message: 11/02/2009, 10h57
  2. [Smarty] Comment accéder aux propriétés d'un objet dans un objet ?
    Par Tanebisse dans le forum Bibliothèques et frameworks
    Réponses: 3
    Dernier message: 18/11/2008, 12h36
  3. comment accéder aux propriétés du modem
    Par kadij dans le forum Windows XP
    Réponses: 4
    Dernier message: 09/06/2008, 11h09
  4. Réponses: 3
    Dernier message: 02/01/2007, 14h09
  5. Réponses: 6
    Dernier message: 25/09/2006, 17h08

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