-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: [Résolu] Mapping bloquant. Set many-to-many non inversé
PostPosted: Fri May 23, 2008 6:21 am 
Beginner
Beginner

Joined: Fri May 23, 2008 4:37 am
Posts: 25
Hibernate version: 3.2.5

Mapping documents:
Quote:
<class name="be.gervaisb.sics.security.Resource" table="resources">
<id name="url"><generator class="assigned" /></id>

<set name="roles" table="resources_roles">
<key column="resUrl" />
<many-to-many
class="be.gervaisb.commons.beans.Role"
column="roleName"
lazy="false"
/>
</set>

</class>

Quote:
<class name="be.gervaisb.commons.beans.Role" table="roles">
<id name="name"><generator class="assigned" /></id>

<property name="description"/>
<property name="enabled" type="java.lang.Boolean"/>
</class>



Code between sessionFactory.openSession() and session.close():
Code:
// Test method content
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 res = new Resource("myresource");
      daoFactory.getResourcesDao().save(res);
      System.out.println("Login saved \n\n");
      
      Role role = new Role("Secretaire");   
      daoFactory.getRoleDao().save(role);
      System.out.println("Role saved \n\n");
      
      role = daoFactory.getRoleDao().get("Secretaire");
      res = daoFactory.getResourcesDao().get("myresource");
      System.out.println("Objects reloaded \n\n");
      System.out.println("\tRole     : "+role);
      System.out.println("\tResource : "+res);
      
      res.addRole(role);      
      daoFactory.getResourcesDao().update(res);
      System.out.println("\n\n Get the resource :\n\t"+
            daoFactory.getResourcesDao().get("myresource"));

Chaque DAO hérite d'une même classe générique dont voici le méthodes principales :
Code:
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;      
   }

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;
   }

public void update(T object) throws DataAccessException {
      logger.debug("Updating %s '%s'.", type.getSimpleName(), object);
      getHibernateTemplate().update(object);
      getHibernateTemplate().flush();
   }

public void remove(T object) throws DataAccessException {
      logger.debug("Removing "+object);
      getHibernateTemplate().delete(object);
   }


Full stack trace of any exception that occurs: No Exceptions

Name and version of the database you are using: PostgreSQL 8.2

The generated SQL (show_sql=true):
Quote:
--Saving resource
2008-05-23 11:04:08,484 DEBUG [org.hibernate.SQL] -
/* insert be.gervaisb.sics.security.Resource
*/ insert
into
resources
(url)
values
(?)
-- Saving role
2008-05-23 11:04:08,531 DEBUG [org.hibernate.SQL] -
/* insert be.gervaisb.commons.beans.Role
*/ insert
into
roles
(description, enabled, name)
values
(?, ?, ?)
-- Loading objects
2008-05-23 11:04:08,546 DEBUG [org.hibernate.SQL] -
/* load be.gervaisb.commons.beans.Role */ select
role0_.name as name0_0_,
role0_.description as descript2_0_0_,
role0_.enabled as enabled0_0_
from
roles role0_
where
role0_.name=?
2008-05-23 11:04:08,578 DEBUG [org.hibernate.SQL] -
/* load be.gervaisb.sics.security.Resource */ select
resource0_.url as url1_0_
from
resources resource0_
where
resource0_.url=?
2008-05-23 11:04:08,578 DEBUG [org.hibernate.SQL] -
/* load collection be.gervaisb.sics.security.Resource.roles */ select
roles0_.resUrl as resUrl1_,
roles0_.roleName as roleName1_,
role1_.name as name0_0_,
role1_.description as descript2_0_0_,
role1_.enabled as enabled0_0_
from
resources_roles roles0_
left outer join
roles role1_
on roles0_.roleName=role1_.name
where
roles0_.resUrl=?
-- Updating resource
2008-05-23 11:04:08,625 DEBUG [org.hibernate.SQL] -
/* delete collection be.gervaisb.sics.security.Resource.roles */ delete
from
resources_roles
where
resUrl=?
-- Re loading resource
2008-05-23 11:04:08,625 DEBUG [org.hibernate.SQL] -
/* load be.gervaisb.sics.security.Resource */ select
resource0_.url as url1_0_
from
resources resource0_
where
resource0_.url=?
2008-05-23 11:04:08,640 DEBUG [org.hibernate.SQL] -
/* load collection be.gervaisb.sics.security.Resource.roles */ select
roles0_.resUrl as resUrl1_,
roles0_.roleName as roleName1_,
role1_.name as name0_0_,
role1_.description as descript2_0_0_,
role1_.enabled as enabled0_0_
from
resources_roles roles0_
left outer join
roles role1_
on roles0_.roleName=role1_.name
where
roles0_.resUrl=?




Debug level Hibernate log excerpt:DEBUG


Mon problème :
J'ai deux objets : 'Role' et 'Resource'; Un 'Role' n'a aucuen référence sur les resources alors qu'une 'Resource' peux contenir un java.util.Set de 'Roles'.

Lorsque je sauve un objet 'Role' tout vas bien. Lorsque je sauve un objet 'Resource' sans roles, tout vas bien.
Lorsque je tente de sauver/mettre à jour un objet 'Resource' qui contiens un 'Role' (ou plus) je n'ai aucune erreurs mais ma table de relation reste vide et donc, à la récupération les 'Roles' ne sont plus repris dans mon objet 'Resource'.

Je ne sais pas ou est est ma faute, sur les forums de Spring, personne ne semble voir l'erreur, je me retourne donc vers le pro d'Hibernate.

Merci

Remarques : J'utilise Spring et HibernateTemplate.


EDIT : EN regradant biens les logs il y à une chose qui me semble bizarre :

Quote:
--> Will update resource with roles :[Role Secretaire (Enabled)]
2008-05-23 13:14:55,859 DEBUG [org.hibernate.impl.SessionImpl] - opened session at timestamp: 12115412958
2008-05-23 13:14:55,859 DEBUG [org.hibernate.transaction.JDBCTransaction] - begin
2008-05-23 13:14:55,859 DEBUG [org.hibernate.jdbc.ConnectionManager] - opening JDBC connection
2008-05-23 13:14:55,859 DEBUG [org.hibernate.transaction.JDBCTransaction] - current autocommit status: true
2008-05-23 13:14:55,859 DEBUG [org.hibernate.transaction.JDBCTransaction] - disabling autocommit
2008-05-23 13:14:55,859 DEBUG [org.hibernate.jdbc.JDBCContext] - after transaction begin
2008-05-23 13:14:55,875 DEBUG [org.hibernate.impl.SessionImpl] - opened session at timestamp: 12115412958
2008-05-23 13:14:55,875 DEBUG [org.hibernate.event.def.DefaultSaveOrUpdateEventListener] - updating detached instance
2008-05-23 13:14:55,875 DEBUG [org.hibernate.event.def.DefaultSaveOrUpdateEventListener] - updating [be.gervaisb.sics.security.Resource#myresource]
2008-05-23 13:14:55,875 DEBUG [org.hibernate.event.def.ReattachVisitor] - collection dereferenced while transient [be.gervaisb.sics.security.Resource.roles#myresource]
2008-05-23 13:14:55,875 DEBUG [org.hibernate.event.def.DefaultSaveOrUpdateEventListener] - updating [be.gervaisb.sics.security.Resource#myresource]
2008-05-23 13:14:55,875 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - flushing session
2008-05-23 13:14:55,875 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - processing flush-time cascades
2008-05-23 13:14:55,875 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - dirty checking collections
2008-05-23 13:14:55,875 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Flushing entities and processing referenced collections
2008-05-23 13:14:55,890 DEBUG [org.hibernate.event.def.WrapVisitor] - Wrapped collection in role: be.gervaisb.sics.security.Resource.roles
2008-05-23 13:14:55,890 DEBUG [org.hibernate.event.def.DefaultFlushEntityEventListener] - Updating entity: [be.gervaisb.sics.security.Resource#myresource]
2008-05-23 13:14:55,890 DEBUG [org.hibernate.engine.Collections] - Collection found: [be.gervaisb.sics.security.Resource.roles#myresource], was: [<unreferenced>] (initialized)
2008-05-23 13:14:55,890 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Processing unreferenced collections
2008-05-23 13:14:55,890 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Scheduling collection removes/(re)creates/updates
2008-05-23 13:14:55,890 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Flushed: 0 insertions, 1 updates, 0 deletions to 1 objects
2008-05-23 13:14:55,890 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - Flushed: 1 (re)creations, 0 updates, 1 removals to 1 collections
2008-05-23 13:14:55,890 DEBUG [org.hibernate.pretty.Printer] - listing entities:
2008-05-23 13:14:55,890 DEBUG [org.hibernate.pretty.Printer] - be.gervaisb.sics.security.Resource{roles=[], url=myresource}
2008-05-23 13:14:55,890 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - executing flush
2008-05-23 13:14:55,890 DEBUG [org.hibernate.jdbc.ConnectionManager] - registering flush begin
2008-05-23 13:14:55,890 DEBUG [org.hibernate.persister.collection.AbstractCollectionPersister] - Deleting collection: [be.gervaisb.sics.security.Resource.roles#myresource]
2008-05-23 13:14:55,890 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to open PreparedStatement (open PreparedStatements: 0, globally: 0)
2008-05-23 13:14:55,890 DEBUG [org.hibernate.jdbc.ConnectionManager] - opening JDBC connection
2008-05-23 13:14:55,953 DEBUG [org.hibernate.SQL] -
/* delete collection be.gervaisb.sics.security.Resource.roles */ delete
from
resources_roles
where
resUrl=?
2008-05-23 13:14:55,953 DEBUG [org.hibernate.SQL] -
/* delete collection be.gervaisb.sics.security.Resource.roles */ delete
from
resources_roles
where
resUrl=?
2008-05-23 13:14:55,953 DEBUG [org.hibernate.jdbc.AbstractBatcher] - preparing statement
2008-05-23 13:14:55,953 DEBUG [org.hibernate.type.StringType] - binding 'myresource' to parameter: 1
2008-05-23 13:14:55,953 DEBUG [org.hibernate.persister.collection.AbstractCollectionPersister] - done deleting collection
2008-05-23 13:14:55,953 DEBUG [org.hibernate.jdbc.AbstractBatcher] - Executing batch size: 1
2008-05-23 13:14:55,953 DEBUG [org.hibernate.jdbc.AbstractBatcher] - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
2008-05-23 13:14:55,953 DEBUG [org.hibernate.jdbc.AbstractBatcher] - closing statement
2008-05-23 13:14:55,953 DEBUG [org.hibernate.persister.collection.AbstractCollectionPersister] - Inserting collection: [be.gervaisb.sics.security.Resource.roles#myresource]
2008-05-23 13:14:55,953 DEBUG [org.hibernate.persister.collection.AbstractCollectionPersister] - collection was empty
2008-05-23 13:14:55,953 DEBUG [org.hibernate.jdbc.ConnectionManager] - registering flush end
2008-05-23 13:14:55,953 DEBUG [org.hibernate.event.def.AbstractFlushingEventListener] - post flush
2008-05-23 13:14:55,953 DEBUG [org.hibernate.impl.SessionImpl] - closing session
2008-05-23 13:14:55,953 DEBUG [org.hibernate.jdbc.ConnectionManager] - performing cleanup
2008-05-23 13:14:55,953 DEBUG [org.hibernate.jdbc.ConnectionManager] - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
2008-05-23 13:14:55,953 DEBUG [org.hibernate.jdbc.JDBCContext] - after transaction completion
2008-05-23 13:14:55,953 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-23 13:14:55,953 DEBUG [org.hibernate.impl.SessionImpl] - after transaction completion
2008-05-23 13:14:55,953 DEBUG [org.hibernate.impl.SessionImpl] - opened session at timestamp: 12115412959
2008-05-23 13:14:55,953 DEBUG [org.hibernate.impl.SessionImpl] - closing session
2008-05-23 13:14:55,953 DEBUG [org.hibernate.jdbc.ConnectionManager] - connection already null in cleanup : no action
2008-05-23 13:14:55,953 DEBUG [org.hibernate.transaction.JDBCTransaction] - commit
2008-05-23 13:14:55,953 DEBUG [org.hibernate.impl.SessionImpl] - automatically flushing session
2008-05-23 13:14:55,968 DEBUG [org.hibernate.jdbc.JDBCContext] - before transaction completion
2008-05-23 13:14:55,968 DEBUG [org.hibernate.impl.SessionImpl] - before transaction completion
2008-05-23 13:14:55,968 DEBUG [org.hibernate.transaction.JDBCTransaction] - re-enabling autocommit
2008-05-23 13:14:55,968 DEBUG [org.hibernate.transaction.JDBCTransaction] - committed JDBC Connection
2008-05-23 13:14:55,968 DEBUG [org.hibernate.jdbc.JDBCContext] - after transaction completion
2008-05-23 13:14:55,968 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-23 13:14:55,968 DEBUG [org.hibernate.impl.SessionImpl] - after transaction completion
-->Resource with roles :[] updated.

Il indioque 'Collection was empty' alors que ce n'est pas le cas, mon Set est bien rempli. (Vu dans le debug de mon IDE, et affiché par yn syso("..."+resource.getRoles()+"..") dans la méthode update de mon DAO[/quote]


Last edited by gervaisb on Fri May 23, 2008 11:04 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Fri May 23, 2008 9:50 am 
Regular
Regular

Joined: Mon Apr 19, 2004 6:54 pm
Posts: 79
As tu bien defini hashCode et equals dans Role?


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 23, 2008 10:10 am 
Beginner
Beginner

Joined: Fri May 23, 2008 4:37 am
Posts: 25
Je les ai redéfinis oui mais je ne sais pas si je les ai *bien* redéfinis :
Code:
public class Role implements Comparable<Role> {
@Override
   public int hashCode() {
      final int prime = 32;
      int hash = getName().hashCode()*prime;
      hash += (getDescription()!=null?getDescription().hashCode():0)*prime;
      return hash;
   }
   
   @Override
   public boolean equals(Object obj) {
      if ( !(obj instanceof Role) )
         return false;
      
      Role that = (Role) obj;
      return   getName()!=null
               ?getName().equals(that.getName())
               :that.getName()==null &&
            getDescription()!=null
               ?getDescription().equals(that.getDescription())
               :that.getDescription()==null;   
   }
}

Code:
public class Resource implements Comparable<Resource> {
@Override
   public int hashCode() {   
      final int prime=12;
      int hash = getUrl().hashCode()*prime;
      for (Role role : getRoles()) {
         hash += role.hashCode()*prime;
      }
      return hash;
   }
   
   @Override
   public boolean equals(Object obj) {
      if ( !(obj instanceof Resource) )
         return false;
      Resource that = (Resource) obj;
      return   getUrl()!=null
               ?getUrl().equals(that.getUrl())
               :that.getUrl()==null &&
            getDescription()!=null
               ?getDescription().equals(that.getDescription())
               :that.getDescription()==null &&
            getRoles()!=null
               ?getRoles().equals(that.getRoles())
               :that.getRoles()==null;
   }
}


Top
 Profile  
 
 Post subject: [Résolu] Cause du problème et Solution
PostPosted: Fri May 23, 2008 10:41 am 
Beginner
Beginner

Joined: Fri May 23, 2008 4:37 am
Posts: 25
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:
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..


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.