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

Persistance des données Java Discussion :

One-to-many et many-to-one


Sujet :

Persistance des données Java

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 69
    Points : 30
    Points
    30
    Par défaut One-to-many et many-to-one
    Hello,

    Je fais suite à un topic que je ne retrouve plus.

    En fait j'essaie de coder une relation many-to-one mais je patine dans la s'moule.

    Déjà, malgré une solide formation et lecture de la section idoine de la doc Hibernate, je ne comprends pas la différence entre une relation many-to-one (recommandé) et une one-to-many ("inhabituel et pas recommandé")

    La one-to-many est liée étroitement au concept de collection, or pourquoi pas la many-to-one ? Niveau objet, dans tous les cas il faudra bien dire que A est un ensemble de B notamment si plusieurs B sont rattachés à un A (many-to-one ?)

    Si vous avez des exemples ce serait sympa car la doc Hibernate n'est pas très causante en cas concrets.

    http://www.hibernate.org/hib_docs/re..._reference.pdf

    (Chapitre 7 - p92)

    Merci.

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

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Quel est exactement ton problème ?
    Le many-to-one représente l'autre côté de la relation one-to-many.
    Je n'ai pas eu de problème en me basant sur les exemples de la documentation.

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 69
    Points : 30
    Points
    30
    Par défaut
    Résumons donc la situation point par point :

    Classes

    J'ai créé une classe Forum et une classe Topic
    A un Forum sont associés 0 à n Topics.

    Attributs de classes

    J'ai créé ma classe Forum avec attribut de la clé primaire for_id
    J'ai créé ma classe Topic avec top_id (correspond a clé primaire) et for_id (correspond à clé étrangère)

    Getters setters et constructeurs

    J'ai les getters et les setters de tous les champs. Pas d'attributs relatifs aux clés primaires dans les constructeurs.

    Fichiers de mapping

    J'ai un id name le hbm du forum

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        	<id name="for_id">
        		<generator class="increment"/>
        	</id>
    J'ai un id name et un many-to-one dans le hbm du topic

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        	<id name="top_id">
        		<generator class="increment"/>
        	</id>
     
            <many-to-one name="for_id"
            			class="Forum"
            			column="for_id"
            			unique="false"
            			not-null="true"/>
    Méthodes

    Dans ma classe Forum j'ai une méthode ajouter Forum et une méthode ajouterTopic qui ouvrent bien des sessionFactory en appelant HibernateUtil, beginTransaction, persist et commit

    Main

    Le main consiste en :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    // 1)
    Forum f = new Forum(...);
    f.ajouterForum();
     
    // 2)
    Topic t = new Topic (...);
    f.ajouterTopic(t);
    Execution / commentaires

    Le 1) fonctionne nickel et ajoute bien mon enreg dans MySQL
    Le 2) plante avec ces Exceptions Hibernate :

    object is not an instance of declaring class
    occurred calling getter of ...Forum.for_id


    Le 2) fonctionne en remplaçant le <many-to-one> par <property name>

    Rien de mieux avec un cascade="all" dans le many-to-one.

    S'il faut un "one-to-many" dans Forum je ne comprends pas pourquoi en tous cas je n'ai pas vu cela en formation et la doc Hibernate déconseille l'usage de one-to-many pour une raison qui m'échappe.

    Merci pour votre attention.

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

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Montre nous le code des méthodes ajouterForum et ajouterTopic et le code d'initialisation de ces objets.

    Tu dois effectivement utiliser un many-to-one côté topic.

    Le truc qui me gène, c'est qu'on parle pas de clef primaire coté Java avec Hibernate, on manipule des objets.
    Ce qui donnerait :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     <many-to-one name="forum"
            			class="Forum"
            			column="for_id"
            			unique="false"
            			not-null="true"/>

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 69
    Points : 30
    Points
    30
    Par défaut
    Forum.ajouterForum:

    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
    19
    20
    	public void ajouterForum(){
     
    		Transaction tx = null;
    		Session session = null;
     
    		session = HibernateUtil.openSession();
     
    		try{
    			tx = session.beginTransaction();
    			session.persist(this);
    			tx.commit();
    		}catch(HibernateException e){
    			System.out.println(e.getCause() + e.getMessage());
    			if(tx != null)
    				tx.rollback();
    			throw e;
    		}finally{
    			session.close();
    		}
    	}
    Forum.ajouterTopic :

    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
    19
    20
    21
    	public void ajouterTopic(Topic t){
     
    		Transaction tx = null;
    		Session session = null;
     
    		session = HibernateUtil.openSession();
     
    		try{
    			tx = session.beginTransaction();
    			session.persist(t);
    			tx.commit();
    		}catch(HibernateException e){
    			System.out.println("Cause" + e.getCause()); 
    			System.out.println ("Message" + e.getMessage());
    			if(tx != null)
    				tx.rollback();
    			throw e;
    		}finally{
    			session.close();
    		}
    	}

    Les constructeurs initialisent tous les attributs saufs ceux qui sont relatifs aux clés primaires car elles sont en auto-incrément, impossible donc les passer en argument on ne sait pas à l'avance ce que ça vaut !

    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Public Forum (String for_libelle, ...)
    et non

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Public Forum (int for_id, String Libelle, ...)

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 69
    Points : 30
    Points
    30
    Par défaut
    Forum.ajouterForum:

    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
    19
    20
    	public void ajouterForum(){
     
    		Transaction tx = null;
    		Session session = null;
     
    		session = HibernateUtil.openSession();
     
    		try{
    			tx = session.beginTransaction();
    			session.persist(this);
    			tx.commit();
    		}catch(HibernateException e){
    			System.out.println(e.getCause() + e.getMessage());
    			if(tx != null)
    				tx.rollback();
    			throw e;
    		}finally{
    			session.close();
    		}
    	}
    Forum.ajouterTopic :

    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
    19
    20
    21
    	public void ajouterTopic(Topic t){
     
    		Transaction tx = null;
    		Session session = null;
     
    		session = HibernateUtil.openSession();
     
    		try{
    			tx = session.beginTransaction();
    			session.persist(t);
    			tx.commit();
    		}catch(HibernateException e){
    			System.out.println("Cause" + e.getCause()); 
    			System.out.println ("Message" + e.getMessage());
    			if(tx != null)
    				tx.rollback();
    			throw e;
    		}finally{
    			session.close();
    		}
    	}

    Les constructeurs initialisent tous les attributs saufs ceux qui sont relatifs aux clés primaires car elles sont en auto-incrément, impossible donc les passer en argument on ne sait pas à l'avance ce que ça vaut !

    Exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Public Forum (String for_libelle, ...)
    et non

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Public Forum (int for_id, String for_libelle, ...)

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 69
    Points : 30
    Points
    30
    Par défaut
    Je précise que si j'ai déjà 2 topics dans ma table topic, l'appel de ajouterTopic donne bien, juste après le persist, visualisé avec "inspect" en mode debug :

    t.top_id=3

    mais le commit plante.

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 69
    Points : 30
    Points
    30
    Par défaut
    ...Après avoir lu différents tutoriaux je n'ai toujours pas compris la différence entre ces 2 relations uni-directionnelles :

    1) Créer une relation one-to-many dans Forum et une collection de Topics définie dans la classe Forum (aucune clé étrangère)

    2) Créer une relation many-to-one dans Topic avec une clé étrangère dans Topic (aucune collection)

    J'ai toutefois compris que l'utilisation conjointe de one-to-many et many-to-one s'applique aux relations bi-directionnelles, ce qui n'est pas notre cas ici.

    Dans un tutoriel ils citent comme exemple

    pour le 1) la relation livre - chapitre
    pour le 2) la relation éditeur - livre

    Merci de bien vouloir m'expliquer...

  9. #9
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    Les deux cas nécessitent quoi qu'il arrive une clé étrangère en base; Hibernate n'est pas magique.

    Tout dépend de ton besoin pour choisir ta relation.
    Si tu as besoin d'avoir, à partir d'un forum, la liste de ses topics, utilise la première solution.
    S'il te suffit d'avoir le forum associé à un topic, choisis la deuxième.
    Si tu as besoin des deux, fais une relation bi-directionnelle.
    Hibernate recommande d'ailleurs l'utilisation de relation bi-directionnelle, pour, entre autre, une meilleure navigation dans les relations, dans les requêtes HQL.

  10. #10
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 69
    Points : 30
    Points
    30
    Par défaut
    Merci pour ton explication claire et précise.

    J'ai résolu mon problème notamment avec ce tutoriel :

    http://mars.iti.pk.edu.pl/~swoosh/_hibernate_tutorial/

    Au Chapitre 4, page 2, le "private Publisher publisher" en gras m'a fait comprendre qu'il fallait référencer un objet et non un ID comme j'avais codé au début, avec le lot d'erreurs qui s'ensuit...

    Pour compléter et clore ce topic je précise que pour que Hibernate charge en mémoire le forum pour un topic donné il faut préciser

    lazy="false"

    dans le <many-to-one> et

    fetch="join"

    pour que le chargement se fasse en un seul SELECT

    Ces options se retrouvent de l'autre côté dans le one-to-many.

    Le tutoriel ci-dessus explique bien tout cela

  11. #11
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 6
    Points : 7
    Points
    7
    Par défaut
    Bonjour,

    j'ai un problème similaire avec hibernate...
    ton lien vers le tutoriel semble ne pas fonctionner... est-ce que tu pourrais le mettre à jour ?

    merci beaucoup.

  12. #12
    Membre du Club
    Inscrit en
    Juillet 2009
    Messages
    106
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 106
    Points : 56
    Points
    56
    Par défaut
    Je relance la discussion suite à une remarque que j ai fait.
    d’après fr1man:l'utilisation de la relation one to many dépend de l'objectif final de l'application.or je crois que en utilisant seulement une relation many to one on peut avoir soit la liste des topic a partir d un forum ou bien le topic associé a chaque forum.Ceci est faisable évidement à travers une requête imbriquée.
    Donc,je ne vois pas ou est la force d'utilisation d une relation one to many

  13. #13
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 274
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 274
    Points : 4 141
    Points
    4 141
    Par défaut
    C'est juste une question de facilité de navigation selon les besoins.

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

Discussions similaires

  1. [HQL] Many to one--Many to many
    Par seb759 dans le forum Hibernate
    Réponses: 6
    Dernier message: 20/12/2011, 13h24
  2. [MAPPING] one-to-one et many-to-many
    Par Invité dans le forum Hibernate
    Réponses: 10
    Dernier message: 09/03/2010, 14h53
  3. Un peu de mal a comprendre le concepte "one-to-many" et "many-to-many"
    Par chriscoolletoubibe dans le forum Hibernate
    Réponses: 4
    Dernier message: 29/03/2007, 18h50
  4. Confusions entre les one/many-to-many/one
    Par TigrouMeow dans le forum Hibernate
    Réponses: 1
    Dernier message: 01/01/2007, 21h44
  5. [Debutant] absence des one-to-many et many-to-one
    Par tck-lt dans le forum Hibernate
    Réponses: 2
    Dernier message: 15/12/2006, 12h33

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