2008-10-08 12 views
3

Je veux comparer la valeur actuelle d'une en mémoire entité Mise en veille prolongée avec la valeur dans la base de données:Hibernate: comparer enregistrement en cours et précédent

HibernateSession sess = HibernateSessionFactory.getSession(); 
MyEntity newEntity = (MyEntity)sess.load(MyEntity.class, id); 
newEntity.setProperty("new value"); 
MyEntity oldEntity = (MyEntity)sess.load(MyEntity.class, id); 
// CODEBLOCK#1 evaluate differences between newEntity and oldEntity 
sess.update(newEntity);  

Dans codeblock # 1 Je reçois que newEntity.getProperty()="new value" ET oldEntity.getProperty()="new value" (alors que je m'attendais à oldEntity.getProperty()="old value", bien sûr). En fait, les deux objets sont exactement les mêmes en mémoire.

Je foiré autour avec HibernateSessionFactory.getSession().evict(newEntity) et a tenté de mettre oldEntity=null pour se débarrasser de (je besoin que pour la comparaison):

HibernateSession sess = HibernateSessionFactory.getSession(); 
MyEntity newEntity = (MyEntity)sess.load(MyEntity.class, id); 
newEntity.setProperty("new value"); 
HibernateSessionFactory.getSession().evict(newEntity); 
MyEntity oldEntity = (MyEntity)sess.load(MyEntity.class, id); 
// CODEBLOCK#1 evaluate differences between newEntity and oldEntity 
oldEntity = null; 
sess.update(newEntity); 

et maintenant les deux entités sont distinctes, mais bien sûr, je reçois la redouté org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session.

Une idée?

EDIT: J'ai essayé la stratégie de double session; Je modifié mon HibernateSessionFactory pour mettre en œuvre une carte de la session, puis ...

Session session1 = HibernateSessionFactory.getSession(SessionKeys.DEFAULT); 
Session session2 = HibernateSessionFactory.getSession(SessionKeys.ALTERNATE); 
Entity newEntity = (Entity)entity; 
newEntity.setNote("edited note"); 
Entity oldEntity = (Entity)session1.load(Entity.class, id); 

System.out.println("NEW:" + newEntity.getNote()); 
System.out.println("OLD: " + oldEntity.getNote()); // HANGS HERE!!! 

HibernateSessionFactory.closeSession(SessionKeys.ALTERNATE); 

Mon test unitaire tout en essayant de se bloque imprimer la note oldEntity ... :-(

Répondre

4

Deux façons printemps à l'esprit:

  1. Evict oldEntity avant d'enregistrer newEntity
  2. Utilisez Session.merge() sur oldEntity pour remplacer la version dans le cache de session (newEntity) avec l'original (oldEntity)

EDIT: d'élaborer un petit, le problème ici est que Hibernate conserve un contexte de persistance, qui est les objets surveillés dans le cadre de chaque session. Vous ne pouvez pas faire update() sur un objet détaché (celui qui n'est pas dans le contexte) alors qu'il y a un objet attaché dans le contexte. Cela devrait fonctionner:

HibernateSession sess = ...; 
MyEntity oldEntity = (MyEntity) sess.load(...); 
sess.evict(oldEntity); // old is now not in the session's persistence context 
MyEntity newEntity = (MyEntity) sess.load(...); // new is the only one in the context now 
newEntity.setProperty("new value"); 
// Evaluate differences 
sess.update(newEntity); // saving the one that's in the context anyway = fine 

et devrait donc ceci:

HibernateSession sess = ...; 
MyEntity newEntity = (MyEntity) sess.load(...); 
newEntity.setProperty("new value"); 
sess.evict(newEntity); // otherwise load() will return the same object again from the context 
MyEntity oldEntity = (MyEntity) sess.load(...); // fresh copy into the context 
sess.merge(newEntity); // replaces old in the context with this one 
+0

Pourriez-vous s'il vous plaît expliquer? J'ai essayé les deux, mais ni travaillé ... peut-être que je le fais mal –

+0

Je l'ai fait avec la stratégie # 2, tnx –

0

Qu'en est-il en utilisant session.isDirty (Le JavaDoc dit que la méthode répondra à la question "Est-ce que n'importe quel SQL serait exécuté si nous vidions cette session?" Bien sûr, cela ne fonctionnerait que si vous aviez une nouvelle session propre pour commencer. .