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 :

Problème de Mapping : plusieurs à plusieurs


Sujet :

Hibernate Java

  1. #1
    Invité
    Invité(e)
    Par défaut Problème de Mapping : plusieurs à plusieurs
    Bonjour,

    J'ai les objets suivants :
    - 'Resource(String url, Set<Role> roles)'
    - 'Role(String name)'
    Une 'Resource' contient un Set de 'Role's. Un 'Role' n'a aucune référence sur les 'Resource's mais peut-être utilisé par plusieurs 'Resource's.
    J'ai fais mon ammping comme indiqué dans la référence :
    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
    <class name="xx.yy.security.Resource" table="resources">
      <id name="url"><generator class="assigned" /></id>
     
      <set name="roles" table="resources_roles">
        <key column="url" />
        <many-to-many
          class="xx.yy.beans.Role"
          column="name" 
          lazy="false" />
      </set>
    </class>
     
    <class name="xx.yy.beans.Role" table="roles">
      <id name="name"><generator class="assigned" /></id>
     
      <property name="description"/>
      <property name="enabled" type="java.lang.Boolean"/>
    </class>
    Tout se passe bien lorsque je sauve une 'Resource' et lorsque je sauve un 'Role'.

    Lorsque je fais l'association 'maResource.addRole(unRole)' et que je sauve, tout semble se passer correctement également sauf que ma table de relation reste vide.

    Si j'ajoute un nouveau (non sauvé) 'Role' pour une 'Resource' et que je sauve cette 'Resource' le 'Role' n'est pas sauvé.

    La console ne me dis rien d'autre que du debug, mes tables sont bien créées par Hibernate avec les bonnes colonnes. Je ne vais vraiemnt pas ou est mon erreur.



    Si l'un d'entre-vous à une idée, je suis preneur. Merci


    Edit : Il semblerait que Hibernate ne voie pas la contenu de ma collection (déclarée comme un Set et réalisée par un TreeSet) après qu'il ai wrappé la collection :

    2008-05-20 18:57:35,109 DEBUG [xx.yy.zz.dao.impl.spring.hibernate.GenericHibernateDao] - Saving Resource 'Resource login.html with roles : [Role Anonymous (Enabled)]'.
    2008-05-20 18:57:35,109 DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Opening Hibernate Session
    2008-05-20 18:57:35,109 DEBUG [org.hibernate.impl.SessionImpl] - opened session at timestamp: 12113026551
    2008-05-20 18:57:35,109 DEBUG [org.hibernate.transaction.JDBCTransaction] - begin
    2008-05-20 18:57:35,109 DEBUG [org.hibernate.jdbc.ConnectionManager] - opening JDBC connection
    2008-05-20 18:57:35,109 DEBUG [org.hibernate.transaction.JDBCTransaction] - current autocommit status: true
    2008-05-20 18:57:35,109 DEBUG [org.hibernate.transaction.JDBCTransaction] - disabling autocommit
    2008-05-20 18:57:35,109 DEBUG [org.hibernate.jdbc.JDBCContext] - after transaction begin
    2008-05-20 18:57:35,109 DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Opening Hibernate Session
    2008-05-20 18:57:35,109 DEBUG [org.hibernate.impl.SessionImpl] - opened session at timestamp: 12113026551
    2008-05-20 18:57:35,109 DEBUG [org.hibernate.event.def.DefaultSaveOrUpdateEventListener] - saving transient instance
    2008-05-20 18:57:35,109 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - generated identifier: login.html, using strategy: org.hibernate.id.Assigned
    2008-05-20 18:57:35,109 DEBUG [org.hibernate.event.def.AbstractSaveEventListener] - saving [xx.yy.zz.security.Resource#login.html]
    2008-05-20 18:57:35,125 DEBUG [org.hibernate.event.def.WrapVisitor] - Wrapped collection in role: xx.yy.zz.security.Resource.roles
    2008-05-20 18:57:35,125 DEBUG [org.springframework.orm.hibernate3.HibernateTemplate] - Eagerly flushing Hibernate session
    2008-05-20 18:57:35,125 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - flushing session
    2008-05-20 18:57:35,125 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - processing flush-time cascades
    2008-05-20 18:57:35,125 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - dirty checking collections
    2008-05-20 18:57:35,125 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Flushing entities and processing referenced collections
    2008-05-20 18:57:35,125 DEBUG [org.hibernate.event.def.WrapVisitor] - Wrapped collection in role: xx.yy.zz.security.Resource.roles
    2008-05-20 18:57:35,140 DEBUG [org.hibernate.engine.Collections] - Collection found: [xx.yy.zz.security.Resource.roles#login.html], was: [<unreferenced>] (initialized)
    2008-05-20 18:57:35,140 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Processing unreferenced collections
    2008-05-20 18:57:35,140 DEBUG [org.hibernate.engine.Collections] - Found collection with unloaded owner: [<unreferenced>]
    2008-05-20 18:57:35,140 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Scheduling collection removes/(re)creates/updates
    2008-05-20 18:57:35,140 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Flushed: 1 insertions, 0 updates, 0 deletions to 1 objects
    2008-05-20 18:57:35,140 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Flushed: 1 (re)creations, 0 updates, 0 removals to 2 collections

    2008-05-20 18:57:35,140 DEBUG [org.hibernate.pretty.Printer] - listing entities:
    2008-05-20 18:57:35,140 DEBUG [org.hibernate.pretty.Printer] - xx.yy.zz.security.Resource{roles=[], url=login.html}
    2008-05-20 18:57:35,140 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - executing flush
    2008-05-20 18:57:35,140 DEBUG [org.hibernate.jdbc.ConnectionManager] - registering flush begin
    2008-05-20 18:57:35,140 DEBUG [org.hibernate.persister.entity.AbstractEntityPersister] - Inserting entity: [xx.yy.zz.security.Resource#login.html]
    2008-05-20 18:57:35,140 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
    2008-05-20 18:57:35,140 DEBUG [org.hibernate.jdbc.ConnectionManager] - opening JDBC connection
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.jdbc.AbstractBatcher] - preparing statement
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.persister.entity.AbstractEntityPersister] - Dehydrating entity: [xx.yy.zz.security.Resource#login.html]
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.type.StringType] - binding 'login.html' to parameter: 1
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.jdbc.AbstractBatcher] - Executing batch size: 1
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.jdbc.AbstractBatcher] - closing statement
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.persister.collection.AbstractCollectionPersister] - Inserting collection: [xx.yy.zz.security.Resource.roles#login.html]
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.persister.collection.AbstractCollectionPersister] - collection was empty
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.jdbc.ConnectionManager] - registering flush end
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - post flush
    2008-05-20 18:57:35,203 DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Closing Hibernate Session
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.impl.SessionImpl] - closing session
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.jdbc.ConnectionManager] - performing cleanup
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.jdbc.ConnectionManager] - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.jdbc.JDBCContext] - after transaction completion
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.jdbc.ConnectionManager] - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.impl.SessionImpl] - after transaction completion
    2008-05-20 18:57:35,203 DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Opening Hibernate Session
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.impl.SessionImpl] - opened session at timestamp: 12113026552
    2008-05-20 18:57:35,203 DEBUG [org.springframework.orm.hibernate3.HibernateTemplate] - Eagerly flushing Hibernate session
    2008-05-20 18:57:35,203 DEBUG [org.springframework.orm.hibernate3.SessionFactoryUtils] - Closing Hibernate Session
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.impl.SessionImpl] - closing session
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.jdbc.ConnectionManager] - connection already null in cleanup : no action
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.transaction.JDBCTransaction] - commit
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.impl.SessionImpl] - automatically flushing session
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.jdbc.JDBCContext] - before transaction completion
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.impl.SessionImpl] - before transaction completion
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.transaction.JDBCTransaction] - re-enabling autocommit
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.transaction.JDBCTransaction] - committed JDBC Connection
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.jdbc.JDBCContext] - after transaction completion
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.jdbc.ConnectionManager] - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
    2008-05-20 18:57:35,203 DEBUG [org.hibernate.impl.SessionImpl] - after transaction completion
    2008-05-20 18:57:35,203 DEBUG [xx.yy.zz.dao.impl.spring.hibernate.GenericHibernateDao] - Object 'Resource login.html with roles : []' saved as Resource with key 'login.html'.
    Edit 2 :
    En plaçant des points débugs sur chaque ligne de ma méthode save, j'ai remarqué que le contenu de ma collection disparaissait juste après le 'getHibernateTemplate().save(object)' :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public PK save(T object) throws DataAccessException {
    		logger.debug("Saving %s '%s'.", type.getSimpleName(), object);
    		PK key = (PK) getHibernateTemplate().save(object);
    		//getHibernateTemplate().flush();
    		logger.debug("Object '%s' saved as %s with key '%s'.", object, type.getSimpleName(), key);
    		return key;		 
    	}
    Dernière modification par Invité ; 20/05/2008 à 19h38.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Je soupçonne mes objets de causer ce problème. En effet, chacun d'eux utilise comme clef/identifiant une String avec comme generateur assigned: 'Resource' est identifié par son attribut 'url' et 'Role' est identifié par son attribut 'name'.

    J'ai bien surcharger hashcode et equals mais comment Hibernate sais t'il différencier les objets sauvés puisqu'ils possèdent déjà un identifiant à leur création ?
    (J'ai peur de ne pas me faire comprendre..)

    Dans le cas d'un objet avec un identifiant génér Hibernate différencie un persisté d'un non persisté grâce à la valeur de son identifiant. Mais dans le cas d'un identifiant assigné, comment fais-il ?

    Peut-être donc ne vois t'il pas qu'il y à eu un modification dans 'Resource' et donc ne le sauve pas.

    Merci

  3. #3
    Membre chevronné
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    1 348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 348
    Points : 1 787
    Points
    1 787
    Par défaut
    Salut Blaise,

    J'avoue malheureusement ne pas avoir trop d'idée pour ton problème. Cependant, à moins que cela n'ait changé, dans mon souvenir Hibernate ne se base pas sur l'id même si elle est auto-générée pour savoir si un objet existe en base, mais sur un champ supplémentaire interne.
    Je ne me souviens plus très précisément de comment on fait un many-to-many en fichier de mapping, mais je suis étonné de ne voir nul part apparaitre le nom de ta table de liaison. C'est normal ?

  4. #4
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Merci pour ta réponse. Le nom de la table se trouve dans la balise <set..>.

  5. #5
    Membre chevronné
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    1 348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 348
    Points : 1 787
    Points
    1 787
    Par défaut
    Va falloir que je m'achète des lunettes ...
    Pour la peine, j'ai reparcourus les docs hibernate et du code que j'avais fait, et tout me semble correct dans ton mapping...
    Effectivement, peut être que cela pose problème avec des generator assigned, mais cela serait assez étonnant.
    Tu pourrais mettre un code où tu :
    -Charges une Resource depuis la base
    -Charges un Role depuis la base
    -Ajoutes le Role à la Resource
    -Update la Resource
    et le log que tu as avec ?

  6. #6
    Invité
    Invité(e)
    Par défaut
    Bien sur !

    > Code de test (cahregment, etc..)
    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
    24
    25
    public static void main(String[] args) {
     
    		org.springframework.core.io.Resource resource = new FileSystemResource("./src/daoContext.xml");
    		BeanFactory factory = new XmlBeanFactory(resource);
    		DaoFactory daoFactory = (DaoFactory) factory.getBean("daoFactory");
     
    		System.out.println("\n\n\n DEBUT \n\n\n");
     
    		Resource login = new Resource("login.html");
    		daoFactory.getResourcesDao().save(login);
    		System.out.println("Login saved \n\n");
     
    		Role roleAnon = new Role("Anonymous");	
    		daoFactory.getRoleDao().save(roleAnon);
    		System.out.println("Role saved \n\n");
     
    		roleAnon = daoFactory.getRoleDao().get("Anonymous");
    		login = daoFactory.getResourcesDao().get("login.html");
    		System.out.println("Objects reloaded \n\n");
     
    		login.addRole(roleAnon);		
    		daoFactory.getResourcesDao().update(login);
    		System.out.println("\n\n Get the resource :\n\t"+daoFactory.getResourcesDao().get("login.html"));
     
    	}
    > Tous mes daos étendant la même classe (Merci les generics) dont voci les méthodes :
    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
    24
    25
    26
    27
    28
    29
    30
     
    public PK save(T object) throws DataAccessException {
    		logger.debug("Saving %s '%s'.", type.getSimpleName(), object);
    		PK key = (PK) getHibernateTemplate().save(object);
    		logger.debug("Object '%s' saved as %s with key '%s'.", object, type.getSimpleName(), key);
    		return key;		 
    	}
     
    	/** 
             * Retrieve an object that was previously saved to the storage using the 
             * indicated key as primary key.
             * @throws <tt>be.gervaisb.sics.exceptions.DataAccessException</tt>
             */
    	@SuppressWarnings("unchecked")
    	public T get(PK key) throws DataAccessException {
    		logger.debug("Getting %s with key '%s'.", type.getSimpleName(), key);
    		T object = (T) getHibernateTemplate().get(type, key);
    		getHibernateTemplate().flush();
    		logger.debug("Return '%s' as %s for key '%s'", object, type.getSimpleName(), key);
    		return object;
    	}
     
    	/** Save changes made to an object
             * @throws <tt>be.gervaisb.sics.exceptions.DataAccessException</tt> 
             */
    	public void update(T object) throws DataAccessException {
    		logger.debug("Updating %s '%s'.", type.getSimpleName(), object);
    		getHibernateTemplate().update(object);
    		getHibernateTemplate().flush();
    	}
    Et enfin, le log (en pièce jointe).

    Merci
    Fichiers attachés Fichiers attachés

  7. #7
    Membre chevronné
    Homme Profil pro
    Directeur technique
    Inscrit en
    Janvier 2007
    Messages
    1 348
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Directeur technique

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 348
    Points : 1 787
    Points
    1 787
    Par défaut
    Malheureusement, tout me semble encore une fois correct
    A ta place, j'essayerais deux pistes :
    1) Changer les id en autonum pour voir si ça résout le problème et voir donc si c'est lié au type d'id
    2) Rendre la relation bi-directionnelle et voir si ça change quelquechose

  8. #8
    Invité
    Invité(e)
    Par défaut
    Non, toujours pas..
    J'ai posté sur le forum Spring aussi étant donné que j'utilise HibrenateTemplate.

    http://www.developpez.net/forums/sho...69#post3291269
    http://forum.springframework.org/sho...569#post181569
    Dernière modification par Invité ; 22/05/2008 à 09h13.

  9. #9
    Invité
    Invité(e)
    Par défaut Resolu
    Ho ! Je veins de trouver. 'Resource' est un Bean existant depuis longtemps (avant que je n'utilise Hibernate) et il ne m'avais jamais posé de problèmes.
    Mais en regardant plus en détail, la méthode setRoles(Set newRoles) avait un comportement bizarre, je l'ai changé et tout vas très bien (ancien focntionnement en commentaire)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public void setRoles(Set<Role> newRoles) {
    		System.out.print("@@\t setRoles ("+newRoles+"of type "+newRoles.getClass()+" in place of "+this.roles+" of type "+this.roles.getClass()+")");
    		/*if ( newRoles!=null ) {
    			System.out.print(" <clean and add> ");
    			this.roles.clear();
    			this.roles.addAll(newRoles);
    		} else {
    			System.out.print(" <create new TreeSet> ");
    			this.roles = new TreeSet<Role>();
    		}*/
    		roles = newRoles;
    		System.out.println("\t new roles is "+this.roles+" of type "+this.roles.getClass());		
    	}
    Lorsque je fesais un clear() sur roles je vidais en même temps le contenu de newRoles..
    Or il semblerait que hibernate aie entre temps été assigné son nouveau Set à celui de mon Objet. La, je dois avouer que ça reste flou.

    La point positif est que je peux continuer à avancer, le négatif est que je ne comprend pas comment est-ce possible que le clear() sur le Set de mon objet Resource aie vidé en même temps le set d'Hibernate..

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

Discussions similaires

  1. Mapping dans un table plusieurs-plusieurs-plusieurs
    Par Invité dans le forum Hibernate
    Réponses: 0
    Dernier message: 03/07/2009, 13h15
  2. Problème liaison plusieurs à plusieurs
    Par Anthony17 dans le forum Access
    Réponses: 16
    Dernier message: 22/05/2006, 17h12
  3. [débutant] Problème de liaison un à plusieurs
    Par Anthony17 dans le forum Access
    Réponses: 7
    Dernier message: 02/05/2006, 14h11
  4. [Mapping]relation plusieurs-vers-plusieurs
    Par berret dans le forum Hibernate
    Réponses: 2
    Dernier message: 21/01/2005, 18h44
  5. Problème requête qui renvoie plusieurs
    Par dai.kaioh dans le forum Langage SQL
    Réponses: 6
    Dernier message: 01/04/2004, 10h07

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