-->
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.  [ 6 posts ] 
Author Message
 Post subject: Utilisation des PreXXXEventListener
PostPosted: Tue Jan 31, 2006 5:48 am 
Regular
Regular

Joined: Tue May 03, 2005 8:19 am
Posts: 53
Location: Paris
Bonjour à tous,

Je pensais utiliser les PreXXXEventListener pour mettre à jour mes objets fonctionnels un peu comme l'aurait fait des Triggers before .

Je m'aperçois que le code de mon Listener est effectivement appelé, mais que les informations ajoutées par ce code à mon objet ne sont pas sauvées en base.

J'ai effectué un test qui montre ce problème lors de l'implémentation d'un PreInsertEventListener . J'ai le même problème sur un PreUpdateEventListener .

J'espère avoir été clair, et que je pourrai trouver une solution de contournement.

A+

Hibernate version:
3.1.1

Mapping documents:
Code:
<hibernate-mapping
      package="org.hibernate.test.event">

   <class name="Person">
      <id name="name"/>
      <property name="majDate"/>
   </class>
</hibernate-mapping>



Specific Code of TestCase:
Code:
   protected void configure(Configuration cfg) {
      cfg.setListener("pre-insert", new MajDatePreInsertEventListener());
   }


Code:
public class MajDatePreInsertEventListener  implements PreInsertEventListener {
   public boolean onPreInsert(PreInsertEvent _event) {
      if (_event.getEntity() instanceof Person) {
         ((Person) _event.getEntity()).setMajDate(new Date());
      }

      return false;
   }
}


Code between sessionFactory.openSession() and session.close():
Code:
Transaction tx = s.beginTransaction();
      Person person = new Person("Lilou");
      s.save(person);
      
      tx.commit();
      s.close();

      //After save, majDate is not null
      assertNotNull(person.getMajDate());
      
      s = openSession();
      tx = s.beginTransaction();
      person = (Person) s.createCriteria(Person.class).uniqueResult();
      assertEquals("Lilou", person.getName());

      //After get, majDate must not null
      //but assert is in failure
      assertNotNull(person.getMajDate());
      
      tx.commit();


Name and version of the database you are using:
Oracle 9i


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 07, 2006 4:10 am 
Regular
Regular

Joined: Tue May 03, 2005 8:19 am
Posts: 53
Location: Paris
Apparement je ne suis pas le seul à avoir le problème, mais je ne trouve aucune solution.

Et en mode debug je me perds un peu.

Le Listener est bien appelé avant le save, en mode pas à pas je vois bien l'insert qui se fait mais avec les valeurs de l'objet avant passage dans le Listener.

L'objet doit être cloné quelque part, mais où ?

En version 2, il me semble que l'on récupérait l'objet de la base après une sauvegarde. En 3, comme je ne fait pas de récupération et qu'hibernate ne me retourne pas d'objet, je manipule l'objet modifié par le listener mais qui n'est pas à jour avec la base de donnée.

Post vers le même pb :
http://forum.hibernate.org/viewtopic.php?p=2290186
http://forum.hibernate.org/viewtopic.php?t=940572
http://forum.hibernate.org/viewtopic.php?t=953934


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 09, 2006 6:32 am 
Regular
Regular

Joined: Tue May 03, 2005 8:19 am
Posts: 53
Location: Paris
Après bien des déboires, voici l'implémentation de mon Listener qui corrige mon problème :

Code:
public class MajDatePreInsertEventListener  implements PreInsertEventListener {
   public boolean onPreInsert(PreInsertEvent _event) {
      if (_event.getEntity() instanceof Person) {
         ((Person) _event.getEntity()).setMajDate(new Date());
      
       //MAJ state values   
      Object[] currentState = _event.getPersister().getPropertyValues(_event.getEntity(),
                                                                       _event.getSource().getEntityMode());
         int[] pos = _event.getPersister().findModified(_event.getState(), currentState,
                                                                      _event.getEntity(), _event.getSource());
         
         for (int i = 0; i < pos.length; i++) {
            _event.getState()[pos[i]] = currentState[pos[i]];
         }
      }
      //END MAJ state values   

      return false;
   }
}


En fait, mon Listener est appelé depuis la classe EntityInsertAction dans la méthode preInsert. Et lors de l'insert ligne 51 de cette même classe, il se base sur les valeurs du tableau state qui n'était pas remis à jour par mon Listener.

Code:
EntityInsertAction execute()
      ...
      boolean veto = preInsert();
      ...
      persister.insert( id, state, instance, session );


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 22, 2006 5:22 pm 
Beginner
Beginner

Joined: Fri Nov 04, 2005 3:51 pm
Posts: 32
Hello,
Sorry, I can't speak French, but it appears that you have resolved the issue with updating property values in onPreInsert. As you know, there is absolutely no assistance on this in the forums for some reason. Looking at your code, I don't really understand the last part regarding EntityInsertAction . How and where are you using it in your code? Did you subclass it? Would you mind sharing any more details?


Thanks!

Google's French tanslation below
---------------------------------------------
Bonjour, désolé, je ne parle pas français, mais il s'avère que vous avez résolu le problème avec mettre à jour des valeurs de propriété dans l'onPreInsert. Comme vous le savez, il n'y a absolument aucune aide sur ceci dans les forum pour quelque raison. Regardant votre code, je ne comprends pas vraiment la dernière partie concernant EntityInsertAction. Comment et où l'employez-vous en votre code? vous sous-classe il? Est-ce que cela vous dérangerait de partager plus de détails? Merci!


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 23, 2006 3:26 am 
Regular
Regular

Joined: Tue May 03, 2005 8:19 am
Posts: 53
Location: Paris
EntityInsertAction est une classe d'Hibernate que je n'ai pas surchargé, mais qui lors de la méthode preInsert appelle l'ensemble des PreInsertEventListener . Puis lors de l'appel à persister.insert( id, state, instance, session ); va effectuer l'appel JDBC en se servant des valeurs du tableau d'objet state pour peupler le PreparedStatement.

J'ai un test qui illustre ce comportement, je peux te l'envoyer.

Voici la stackTace jusqu'au peuplement du prepared statement
Code:

// Write the values of fields onto the prepared statement - we MUST use the state at the time the
// insert was issued (cos of foreign key constraints). Not necessarily the object's current state

dehydrate( id, fields, notNull, propertyColumnInsertable, j, insert, session );

SingleTableEntityPersister(AbstractEntityPersister).insert(Serializable, Object[], boolean[], int, String, Object, SessionImplementor) line: 2059
SingleTableEntityPersister(AbstractEntityPersister).insert(Serializable, Object[], Object, SessionImplementor) line: 2427
EntityInsertAction.execute() line: 51
ActionQueue.execute(Executable) line: 243
ActionQueue.executeActions(List) line: 227
ActionQueue.executeActions() line: 140
DefaultFlushEventListener(AbstractFlushingEventListener).performExecutions(EventSource) line: 296
DefaultFlushEventListener.onFlush(FlushEvent) line: 27
SessionImpl.flush() line: 1009
SessionImpl.managedFlush() line: 356
JDBCTransaction.commit() line: 106
PreXXXEventTest.testPreInsert() line: 27


Top
 Profile  
 
 Post subject:
PostPosted: Fri Feb 24, 2006 1:15 am 
Beginner
Beginner

Joined: Fri Nov 04, 2005 3:51 pm
Posts: 32
Approuvez, merci. Je l'étudierai. Je pense que vous êtes un très du peu de peuple pour obtenir ceci pour fonctionner.


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