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 :

[Mapping] Relation père fils sur une même table.


Sujet :

Hibernate Java

  1. #1
    Invité
    Invité(e)
    Par défaut [Mapping] Relation père fils sur une même table.
    Bonjour,

    Je tente de mapper un menu, une relation père-fils sur une même table. Mon mapping "fonctionne" sauf que je récupère toujours le père en tant que fils. Alors que ma table est correctement remplie, à savoir : null pour le parentid.

    Je Détaille :

    J'ai une table menu qui contient entre autre un clef primaire 'id' et une clef étrangère 'parentId'. Je me base sur la valeur de 'parentId' pour reconstruire mon arborescence (menu). Si 'parentId' est null, je considère que l'entrée ud menu est une racine (menu principal).

    La table
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    CREATE TABLE menu (
      id INTEGER PRIMARY KEY,
      parentid INTEGER,
      libelle CHARACTER VARYING,
      CONSTRAINT menu_pk PRIMARY KEY (id),
      CONSTRAINT menu_fk_menu FOREIGN KEY (parentid)
          REFERENCES menu (id) ON UPDATE CASCADE ON DELETE CASCADE,
    )
    INSERT INTO menu (id, parentid, libelle) VALUES (1, null, 'Racine1 sans enfants');
    INSERT INTO menu (id, parentid, libelle) VALUES (2, null, 'Racine2 avec enfants');
    INSERT INTO menu (id, parentid, libelle) VALUES (3, 2, 'Enfant1 de Racine2');
    INSERT INTO menu (id, parentid, libelle) VALUES (4, 2, 'Enfant2 de Racine2');
    INSERT INTO menu (id, parentid, libelle) VALUES (5, 4, 'Enfant1 de Enfant2 de  Racine2');
    Mon objet :
    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
    public class Entry implements Comparable<Entry>, Serializable {
      private Integer id;
      private Entry parent;
      private Set<Entry> childs;
      private String libelle;	
     
      public void setParent(Entry p) {
        if ( p!=null && !p.getChilds().contains(this) )
          p.getChilds().add(this);	
        this.parent = p;
      }
     
      public void setChilds(Set<Entry> childs) {
        this.childs = childs;
        for (Entry child : childs) {
          child.setParent(this);
        }
      }
      // autres accesseurs tout simples (this.truc = paramTruc)
    Mon mapping :
    <hibernate-mapping>
    <class name="xx.yy.Entry" table="menu">
    <id name="id" type="java.lang.Integer">
    <generator class="native" />
    </id>

    <property name="libelle" />

    <many-to-one
    name="parent"
    class="xx.yy.Entry"
    column="parentId"
    lazy="false"
    />
    <set name="childs" inverse="true" lazy="false">
    <key column="id" />
    <one-to-many class="xx.yy.Entry"/>
    </set>
    </class>
    </hibernate-mapping>
    Mon code de test :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Entry home = new Entry("home.html", "home");
    		menuDao.save(home);
    		Entry cotations = new Entry("cotations.html", "cotations");
    		menuDao.save(cotations);
     
    		Set<Entry> roots = menuDao.getRoots();
    		for (Entry entry : roots) {
    			Set<Entry> childs = entry.getChilds();
    			System.out.println("\nRoot "+entry+" has "+childs+" childs.");
    			for (Entry child : childs) {
    				System.out.println("\t - "+child);
    			}
    		}
    Et la console :
    2008-06-09 10:57:53,984 DEBUG [org.hibernate.SQL] -
    select
    nextval ('hibernate_sequence')
    2008-06-09 10:57:54,046 DEBUG [org.hibernate.SQL] -
    /* insert xx.yy.Entry
    */ insert
    into
    menu
    (libelle, description, icon, ordering, target, parentId, id)
    values
    (?, ?, ?, ?, ?, ?, ?)
    2008-06-09 10:57:54,062 DEBUG [org.hibernate.SQL] -
    select
    nextval ('hibernate_sequence')
    2008-06-09 10:57:54,062 DEBUG [org.hibernate.SQL] -
    /* insert xx.yy.Entry
    */ insert
    into
    menu
    (libelle, description, icon, ordering, target, parentId, id)
    values
    (?, ?, ?, ?, ?, ?, ?)
    2008-06-09 10:57:54,093 DEBUG [org.hibernate.SQL] -
    /* criteria query */ select
    this_.id as id0_0_,
    this_.libelle as libelle0_0_,
    this_.description as descript3_0_0_,
    this_.icon as icon0_0_,
    this_.ordering as ordering0_0_,
    this_.target as target0_0_,
    this_.parentId as parentId0_0_
    from
    menu this_
    where
    this_.parentId is null
    2008-06-09 10:57:54,093 DEBUG [org.hibernate.SQL] -
    /* load one-to-many xx.yy.Entry.childs */ select
    childs0_.id as id1_,
    childs0_.id as id0_0_,
    childs0_.libelle as libelle0_0_,
    childs0_.description as descript3_0_0_,
    childs0_.icon as icon0_0_,
    childs0_.ordering as ordering0_0_,
    childs0_.target as target0_0_,
    childs0_.parentId as parentId0_0_
    from
    menu childs0_
    where
    childs0_.id=?
    2008-06-09 10:57:54,140 DEBUG [org.hibernate.SQL] -
    /* load one-to-many xx.yy.Entry.childs */ select
    childs0_.id as id1_,
    childs0_.id as id0_0_,
    childs0_.libelle as libelle0_0_,
    childs0_.description as descript3_0_0_,
    childs0_.icon as icon0_0_,
    childs0_.ordering as ordering0_0_,
    childs0_.target as target0_0_,
    childs0_.parentId as parentId0_0_
    from
    menu childs0_
    where
    childs0_.id=?
    2008-06-09 10:57:54,140 DEBUG [org.hibernate.SQL] -
    /* load one-to-many xx.yy.Entry.childs */ select
    childs0_.id as id1_,
    childs0_.id as id0_0_,
    childs0_.libelle as libelle0_0_,
    childs0_.description as descript3_0_0_,
    childs0_.icon as icon0_0_,
    childs0_.ordering as ordering0_0_,
    childs0_.target as target0_0_,
    childs0_.parentId as parentId0_0_
    from
    menu childs0_
    where
    childs0_.id=?
    2008-06-09 10:57:54,140 DEBUG [org.hibernate.SQL] -
    /* load one-to-many xx.yy.Entry.childs */ select
    childs0_.id as id1_,
    childs0_.id as id0_0_,
    childs0_.libelle as libelle0_0_,
    childs0_.description as descript3_0_0_,
    childs0_.icon as icon0_0_,
    childs0_.ordering as ordering0_0_,
    childs0_.target as target0_0_,
    childs0_.parentId as parentId0_0_
    from
    menu childs0_
    where
    childs0_.id=?
    2008-06-09 10:57:54,156 DEBUG [org.hibernate.SQL] -
    /* load one-to-many xx.yy.Entry.childs */ select
    childs0_.id as id1_,
    childs0_.id as id0_0_,
    childs0_.libelle as libelle0_0_,
    childs0_.description as descript3_0_0_,
    childs0_.icon as icon0_0_,
    childs0_.ordering as ordering0_0_,
    childs0_.target as target0_0_,
    childs0_.parentId as parentId0_0_
    from
    menu childs0_
    where
    childs0_.id=?
    2008-06-09 10:57:54,156 DEBUG [org.hibernate.SQL] -
    /* load one-to-many xx.yy.Entry.childs */ select
    childs0_.id as id1_,
    childs0_.id as id0_0_,
    childs0_.libelle as libelle0_0_,
    childs0_.description as descript3_0_0_,
    childs0_.icon as icon0_0_,
    childs0_.ordering as ordering0_0_,
    childs0_.target as target0_0_,
    childs0_.parentId as parentId0_0_
    from
    menu childs0_
    where
    childs0_.id=?
    2008-06-09 10:57:54,156 DEBUG [org.hibernate.SQL] -
    /* load one-to-many xx.yy.Entry.childs */ select
    childs0_.id as id1_,
    childs0_.id as id0_0_,
    childs0_.libelle as libelle0_0_,
    childs0_.description as descript3_0_0_,
    childs0_.icon as icon0_0_,
    childs0_.ordering as ordering0_0_,
    childs0_.target as target0_0_,
    childs0_.parentId as parentId0_0_
    from
    menu childs0_
    where
    childs0_.id=?
    2008-06-09 10:57:54,156 DEBUG [org.hibernate.SQL] -
    /* load one-to-many xx.yy.Entry.childs */ select
    childs0_.id as id1_,
    childs0_.id as id0_0_,
    childs0_.libelle as libelle0_0_,
    childs0_.description as descript3_0_0_,
    childs0_.icon as icon0_0_,
    childs0_.ordering as ordering0_0_,
    childs0_.target as target0_0_,
    childs0_.parentId as parentId0_0_
    from
    menu childs0_
    where
    childs0_.id=?
    2008-06-09 10:57:54,156 DEBUG [org.hibernate.SQL] -
    /* load one-to-many xx.yy.Entry.childs */ select
    childs0_.id as id1_,
    childs0_.id as id0_0_,
    childs0_.libelle as libelle0_0_,
    childs0_.description as descript3_0_0_,
    childs0_.icon as icon0_0_,
    childs0_.ordering as ordering0_0_,
    childs0_.target as target0_0_,
    childs0_.parentId as parentId0_0_
    from
    menu childs0_
    where
    childs0_.id=?
    2008-06-09 10:57:54,156 DEBUG [org.hibernate.SQL] -
    /* load one-to-many xx.yy.Entry.childs */ select
    childs0_.id as id1_,
    childs0_.id as id0_0_,
    childs0_.libelle as libelle0_0_,
    childs0_.description as descript3_0_0_,
    childs0_.icon as icon0_0_,
    childs0_.ordering as ordering0_0_,
    childs0_.target as target0_0_,
    childs0_.parentId as parentId0_0_
    from
    menu childs0_
    where
    childs0_.id=?

    Root Entry cotations with parent : cotations and 1 childs. has [Entry cotations with parent : cotations and 1 childs.] childs.
    - Entry cotations with parent : cotations and 1 childs.

    Root Entry home with parent : home and 1 childs. has [Entry home with parent : home and 1 childs.] childs.
    - Entry home with parent : home and 1 childs.
    Merci

    Edit :
    J'ai modifié mon mapping pour ceci :
    <set name="childs" lazy="false" inverse="true" cascade="all">
    <key column="parentid"/>
    <one-to-many class="be.gervaisb.menu.Entry"/>
    </set>

    <many-to-one name="parent"
    class="be.gervaisb.menu.Entry"
    column="parentid"
    lazy="false" />
    Et les accesseurs pour ceci :
    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
    22
    23
    public void setParent(Entry p) {
    		if ( this.equals(p) ) {
    			System.err.println("Parent identique à l'enfant");
    			return;
    		}
     
    		if ( p==null ) {
    			this.parent = null;
    		} else if ( !p.equals(this.parent) ) {
    			this.parent = p;
    			p.addChild(this);
    		}
    	}
    public void setChilds(Set<Entry> childs) {
    		this.childs = childs;
    		for (Entry child : this.childs) {
    			child.setParent(this);
    		}
    	}
    public void addChild(Entry child) {
    		child.setParent(this);
    		childs.add(child);
    	}
    Et maintenant j'obtiens l'exeception suivante :
    Exception in thread "main" org.hibernate.PropertyAccessException: Exception occurred inside setter of xx.yy.Entry.childs
    at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:65)
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:337)
    at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:200)
    at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3566)
    at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:129)
    at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:854)
    at org.hibernate.loader.Loader.doQuery(Loader.java:729)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
    at org.hibernate.loader.Loader.doList(Loader.java:2220)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
    at org.hibernate.loader.Loader.list(Loader.java:2099)
    at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:94)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1569)
    at org.hibernate.impl.CriteriaImpl.list(CriteriaImpl.java:283)
    at xx.yy.zz.hibernate.SpringHibernateMenuDao.getRoots(SpringHibernateMenuDao.java:46)
    at xx.yy.zz.Test.main(Test.java:56)
    Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:42)
    ... 15 more
    Caused by: org.hibernate.PropertyAccessException: Exception occurred inside setter of xx.yy.Entry.parent
    at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:65)
    at org.hibernate.tuple.entity.AbstractEntityTuplizer.setPropertyValues(AbstractEntityTuplizer.java:337)
    at org.hibernate.tuple.entity.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:200)
    at org.hibernate.persister.entity.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:3566)
    at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:129)
    at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:854)
    at org.hibernate.loader.Loader.doQuery(Loader.java:729)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
    at org.hibernate.loader.Loader.loadCollection(Loader.java:1994)
    at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:36)
    at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:565)
    at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:60)
    at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1716)
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:344)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
    at org.hibernate.collection.PersistentSet.iterator(PersistentSet.java:163)
    at xx.yy.Entry.setChilds(Entry.java:206)
    ... 20 more
    Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.hibernate.property.BasicPropertyAccessor$BasicSetter.set(BasicPropertyAccessor.java:42)
    ... 36 more
    Caused by: org.hibernate.LazyInitializationException: illegal access to loading collection
    at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:341)
    at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
    at org.hibernate.collection.AbstractPersistentCollection.readElementExistence(AbstractPersistentCollection.java:142)
    at org.hibernate.collection.PersistentSet.add(PersistentSet.java:187)
    at xx.yy.Entry.addChild(Entry.java:197)
    at xx.yy.Entry.setParent(Entry.java:158)
    ... 41 more
    Merci
    Dernière modification par Invité ; 09/06/2008 à 16h06.

  2. #2
    Invité
    Invité(e)
    Par défaut Solution !!
    Pour les pressés : j'ai changé le contenu des méthodes 'setChilds(Tree<Entry> newChilds)' et 'setParent(Entry newParenr)' pour celui-ci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public void setParent(Entry newParent) {
      parent = newParent;
    }
     
    public void setChilds(Set<Entry> newChilds) {
      childs=newChilds;
    }
    Pour ceux qui en veulent plus (et qui voudraient m'aider à comprendre) :
    Mes méthodes 'setChils(Tree<Entry> newChilds)' et 'setParent(Entry newParenr)' étaient un peu plus complexe :
    - setChilds(Tree<Entry> newChilds) : parcourais tous les enfants pour leur affecter this en tant que parent.
    - setParent(Entry newParent) : vérifiait que le newParent n'était pas le parent actuel et ajoutait this en tant qu'enfant.

    J'avais fais celà car il me semblait qu'il était important de s'assurer que les relations soient bien établies entre parent et enfants. Hors il semble que ça fasse l'effet inverse (amène des erreurs au lieu d'en éviter).

    Est-ce moi qui n'ai (encore) rien compris ou autre chose ?
    Merci

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

Discussions similaires

  1. [1.x] relation many to many sur une même table.
    Par thomas974 dans le forum Symfony
    Réponses: 4
    Dernier message: 03/09/2010, 19h55
  2. Réponses: 1
    Dernier message: 19/05/2010, 20h31
  3. Relation père / fils sur une même table
    Par useramina dans le forum JPA
    Réponses: 0
    Dernier message: 03/05/2009, 14h44
  4. relation n-n sur une même table
    Par Tanebisse dans le forum MySQL
    Réponses: 6
    Dernier message: 06/11/2008, 10h36
  5. Hibernate Mapping sur une même table
    Par bubule22 dans le forum Hibernate
    Réponses: 2
    Dernier message: 26/09/2008, 18h24

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