-->
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.  [ 5 posts ] 
Author Message
 Post subject: [Debutant] implémenter un HashMap
PostPosted: Tue Oct 18, 2005 12:57 pm 
Beginner
Beginner

Joined: Tue Oct 18, 2005 10:47 am
Posts: 20
Location: Basel
Bonjour à tous !

Je cherche à implémenter quelque chose d'assez banal avec Hibernate : un HashMap. J'ai regardé la doc. mais soit je la lis mal, soit elle est obsolète sur ce point. Car je vois souvent le bout de code suivant :
Code:
<map name="holidays" order-by="hol_date, hol_name">
     <key column="year_id"/>
     <map-key column="hol_name" type="string"/>
     <element column="hol_date type="date"/>
</map>

Or, quand je jete un oeil au DTD, je constate qu'on ne peut définir de balise <map-key> dans une balise <map> :
Code:
<!ELEMENT map (
    meta*,
    subselect?,
    cache?,
    synchronize*,
    comment?,
    key,
    (map-key | composite-map-key | map-key-many-to-many | index | composite-index | index-many-to-many | index-many-to-any),
    (element | one-to-many | many-to-many | composite-element | many-to-any),
    loader?,sql-insert?,sql-update?,sql-delete?,sql-delete-all?,
    filter*
)>

J'obtiens la confirmation de ceci quand j'essaye de faire marcher mon application :
Code:
ERROR - Error parsing XML: XML InputStream(17) The content of element type "map" must match "(meta*, cache?, synchronize*, key, (index|composite-index|index-many-to-many|index-many-to-any), (element|one-to-many|many-to-many|composite-element|many-to-any), loader?, sql-insert?, sql-update?, sql-delete?, sql-delete-all?, filter*)".


Donc je suis un peu perplexe. Si quelqu'un pouvait éclairer ma lanterne...

Merci d'avance,
Joël.

P.S.: J'apprécierai également toute aide permettant de mettre en place ce HashMap (liens, explications,...)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 18, 2005 9:36 pm 
Newbie

Joined: Wed Oct 12, 2005 9:20 pm
Posts: 16
Location: Sydney
Bonjour,


Euh ... dans l'exemple que vous avez donne je vois :
Quote:
<!ELEMENT map (
...
key,
(map-key | ...
...
)>


J'ai verifie egalement avec la DTD et je confirme que <map-key> est bien une clef de map.


Pourriez-vous donner l'integralite de votre trace d'erreur et l'integralite du fichier de mapping ?

Pourriez vous preciser un peu plus le type de Map que vous voulez persister ?


Ben


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 18, 2005 9:42 pm 
Newbie

Joined: Wed Oct 12, 2005 9:20 pm
Posts: 16
Location: Sydney
Je viens de regarder la DTD de Hibernate 2.0.

Code:
<!ELEMENT map (
   meta*,
   (cache|jcs-cache)?,
   key,
   (index|composite-index|index-many-to-many|index-many-to-any),
   (element|one-to-many|many-to-many|composite-element|many-to-any)
)>


Je trouve que cela cerrespond mieux a l'erreur que vous avez.

Je pense que la declaration de la DTD dans le DOCTYPE de votre fichier de mapping est erronee.

Vous devez avoir ca :
Code:
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">


Bonne chance.


Ben


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 19, 2005 4:08 am 
Beginner
Beginner

Joined: Tue Oct 18, 2005 10:47 am
Posts: 20
Location: Basel
Bonjour et merci pour ces réponses aussi rapides.

Alors effectivement je viens de constater que dans le DTD tout est correct, effectivement. Je ne sais pas pourquoi, mais il me semblait que seuls les index étaient autorisés dans les maps. Quoiqu'il en soit, voici mes classes :

AnnotationState
Code:
package eserve;

import eserve.bom.pojo.AbstractPOJOInstance;

public class AnnotationState extends AbstractPOJOInstance {
   static final long serialVersionUID = -26057400L;

   private java.lang.String id;
   private java.lang.String iso_language_code;
   private java.lang.String ml_id;
   private java.lang.String title;

   public AnnotationState(){}
   
   public java.lang.String getId() {
      return id;
   }
   public void setId(java.lang.String id){
      this.id = id;
   }
   
   public java.lang.String getIso_language_code() {
      return iso_language_code;
   }
   public void setIso_language_code(java.lang.String iso_language_code){
      this.iso_language_code = iso_language_code;
   }
   
   public java.lang.String getMl_id() {
      return ml_id;
   }
   public void setMl_id(java.lang.String ml_id){
      this.ml_id = ml_id;
   }
   
   public java.lang.String getTitle() {
      return title;
   }
   public void setTitle(java.lang.String title){
      this.title = title;
   }
   

  public String getInstanceKeyString() {
     return id == null ? null : id.toString();
  }
 
  public int hashCode() {
     return id == null ? -421 : id.hashCode();
  }
 
     public boolean equals(Object object) {
      if(object instanceof AnnotationState) {
         return id != null &&  id.equals(((AnnotationState)object).id);
      }
      return false;
   }
}


AnnotationStateML
Code:
package eserve;

import eserve.bom.pojo.AbstractPOJOInstance;

public class AnnotationStateML extends AbstractPOJOInstance {
   static final long serialVersionUID = -2006079L;

   private java.lang.String annotation;
   private java.lang.String endActivityDesc;
   private java.lang.String flowModelID;
   private java.lang.String id;
   private java.util.Map name = new java.util.HashMap();
   private java.lang.String startActivityDesc;

   public AnnotationStateML(){}
   
   public java.lang.String getAnnotation() {
      return annotation;
   }
   public void setAnnotation(java.lang.String annotation){
      this.annotation = annotation;
   }
   
   public java.lang.String getEndActivityDesc() {
      return endActivityDesc;
   }
   public void setEndActivityDesc(java.lang.String endActivityDesc){
      this.endActivityDesc = endActivityDesc;
   }
   
   public java.lang.String getFlowModelID() {
      return flowModelID;
   }
   public void setFlowModelID(java.lang.String flowModelID){
      this.flowModelID = flowModelID;
   }
   
   public java.lang.String getId() {
      return id;
   }
   public void setId(java.lang.String id){
      this.id = id;
   }
   
   public java.util.Map getName() {
      return name;
   }
   public void setName(java.util.Map name){
      this.name = name;
   }
   
   public java.lang.String getStartActivityDesc() {
      return startActivityDesc;
   }
   public void setStartActivityDesc(java.lang.String startActivityDesc){
      this.startActivityDesc = startActivityDesc;
   }
   

  public String getInstanceKeyString() {
     return id == null ? null : id.toString();
  }
 
  public int hashCode() {
     return id == null ? -421 : id.hashCode();
  }
 
     public boolean equals(Object object) {
      if(object instanceof AnnotationStateML) {
         return id != null &&  id.equals(((AnnotationStateML)object).id);
      }
      return false;
   }
}


Ce sont des classes générées, mais je ne pense pas que ça pose problème. J'ai rempli le fichier de conf. de hibernate de la manière standard, je pense :

hibernate.cfg.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
   <session-factory>
      <!--Database connection settings-->
      <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
      <property name="connection.url">jdbc:mysql://localhost:3306/ess_competence</property>
      <property name="connection.username">root</property>
      <property name="connection.password"/>
      <property name="connection.pool_size">10</property>
      
      <!--SQL dialect-->
      <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
      
      <!--Echo all executed SQL to stdout-->
      <property name="show_sql">true</property>

      <!--Mappings to load for each defined class-->
      <mapping resource="AnnotationState.hbm.xml"/>
      <mapping resource="AnnotationStateML.hbm.xml"/>
   </session-factory>
</hibernate-configuration>


Et les deux fichiers de conf pour les classes sont les suivants :

AnnotationState.hbm.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="eserve">
   <class name="AnnotationState" table="ANNOTATION_STATE_ML_CONT">
      <id name="id">
         <generator class="assigned"/>
      </id>
      <property name="iso_language_code"/>
      <many-to-one name="ml_id" class="AnnotationStateML" not-null="true"/>
      <property name="title"/>
   </class>
</hibernate-mapping>


AnnotationStateML
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="eserve">
   <class name="AnnotationStateML" table="ANNOTATION_STATE">
      <id name="id">
         <generator class="assigned"/>
      </id>
      <property name="annotation"/>
      <property name="endActivityDesc" column="end_activity_desc"/>
      <property name="flowModelID" column="flow_model_id"/>
      <property name="startActivityDesc" column="start_activity_desc"/>
      <map name="name" inverse="true" cascade="all-delete-orphan">
         <key column="ML_ID"/>
         <!--<map-key column="ISO_LANGUAGE_CODE"/>-->
         <index column="ISO_LANGUAGE_CODE" type="string"/>
         <one-to-many class="AnnotationState"/>
      </map>
   </class>
</hibernate-mapping>


Bon on pourrait croire qu'il y a un problème avec les noms des tables, mais ce n'est pas le cas : les noms ont été interverti pour je ne sais quelle raison et maintenant on ne peux plus le changer :/ (base en production)
Le véritable problème, c'est que je ne parviens pas à persister l'objet AnnotationStateML comme je le souhaiterais. En effet, le code que j'aimerais exécuter est le suivant :


Code:
      BOMClassManager iface = bomRepository.getBOMClassManager();
     
      // Test of the map : insert values to a map. 
      InstanceIntf instanceFR = iface.getClassIntf("AnnotationState").createInstance();
      InstanceIntf instanceDE = iface.getClassIntf("AnnotationState").createInstance();
      instanceFR.setAttrValue("title","version francaise");
      instanceFR.setAttrValue("iso_language_code","FR");
      instanceDE.setAttrValue("title","deutsche version");
      instanceDE.setAttrValue("iso_language_code","DE");
       
      // Test of the map : connect the preceding values to the map. 
      InstanceIntf instanceMap = iface.getClassIntf("AnnotationStateML").createInstance();
      instanceMap.setAttrValue("annotation","this the first map handled by hibernate");
      instanceMap.setAttrValue("endActivityDesc","END");
      instanceMap.setAttrValue("flowModelID","no idea ;)");
      instanceMap.setAttrValue("startActivityDesc","BEGIN");

      Map map = (Map)instanceMap.getAttrValue("name");
      map.put("FR",instanceFR);
      map.put("DE",instanceDE);
      instanceMap.setAttrValue("name",map);

      Session s = this.hibernateRepository.currentSession();
      Transaction tx = s.beginTransaction();
      s.save(instanceMap);
      tx.commit();

Je ne vais pas rentrer dans le détail mais en gros, BOMClassManager est une factory d'objets, et InstanceIntf est une instance d'une classe d'un certain type. Tout ceci fonctionnait avant hibernate, donc je ne pense pas que le problème vienne de là. Ce qui se passe, c'est que lorsque je fais le commit, j'obtiens l'erreur suivante :
Code:
org.hibernate.PropertyValueException: not-null property references a null or transient value: eserve.AnnotationState.ml_id
   at org.hibernate.engine.Nullability.checkNullability(Nullability.java:72)
   at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:164)
   at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:190)
   at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:70)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:324)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
   at eserve.components.hibernate.HibernateComponent.doStart(HibernateComponent.java:107)
...

Il semblerait donc qu'hibernate ne remplisse pas le champ ml_id automatiquement. Je pense que mes fichiers de mapping ne sont pas corrects mais je ne vois pas trop où (ce qui m'aiderai beaucoup serait déjà de savoir s'ils sont corrects et adaptés à ce que je veux faire). Si j'enlève la clause not-null, Hibernate tente de faire un update sur les objets instanceFR et instanceDE au lieu de les insérer dans la base.

Voilà, j'ai mis à peu près tout ce dont je dispose. Désolé pour la taille de ce message abominablement grand, mais j'ai préféré tout mettre pour que ce soit plus "clair" ;)

A bientôt,
Joël.


Top
 Profile  
 
 Post subject: Du neuf...
PostPosted: Thu Oct 20, 2005 2:55 am 
Beginner
Beginner

Joined: Tue Oct 18, 2005 10:47 am
Posts: 20
Location: Basel
Bonjour !

J'ai du neuf concernant mon erreur. Il s'agissait en fait de la version en cache local de ma DTD qui n'était pas bonne. J'ai mis celle venant de sourceforge et je n'ai plus eu de problème de mapping avec <map-key>.

Maintenant, le problème que j'ai c'est qu'hibernate ne remplit pas automatiquement le champ ml_id d'AnnotationState.

Pour rappel, Les objets AnnotationState sont en fait les éléments qui vont être liés aux objets AnnotationStateML par le biais du HasMap. Le champ ml_id permet justement de pouvoir lier ces deux tables au niveau de la base de données (ml_id est en fait la clé étrangére pointant sur la clé primaire de la table Annotation_State, la colonne 'id').

Lorsque je fais session.save(monObjetAnnotationStateML); j'obtiens toujours le message d'erreur :
Code:
org.hibernate.PropertyValueException: not-null property references a null or transient value: eserve.AnnotationState.ml_id
   at org.hibernate.engine.Nullability.checkNullability(Nullability.java:72)
   at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:164)
   at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:190)
   at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:70)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:26)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:324)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)


J'ai attaché les sources d'Hibernate à mon débugger, mais je ne vois pas trop ou il est censé faire la mise à jour de ml_id. Est ce que quelqu'un pourrait me conseiller sur ce qu'il faudrait que je tente, j'ai l'impression de tourner en rond avec mes "expériences".

Merci d'avance,
Joël.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 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.