Hibernate: comparing current & previous record

江枫思渺然 提交于 2021-02-12 05:16:51

问题


I want to compare the current value of an in-memory Hibernate entity with the value in the database:

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

In CODEBLOCK#1 I get that newEntity.getProperty()="new value" AND oldEntity.getProperty()="new value" (while I expected oldEntity.getProperty()="old value", of course). In fact the two objects are exactly the same in memory.

I messed around with HibernateSessionFactory.getSession().evict(newEntity) and attempted to set oldEntity=null to get rid of it (I need it only for the comparison):

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

and now the two entities are distinct, but of course I get the dreaded org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session.

Any idea?

EDIT: I tried the double session strategy; I modified my HibernateSessionFactory to implement a map of session and then...

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

My unit test hangs while attempting to print the oldEntity note... :-(


回答1:


Two easy options spring to mind:

  1. Evict oldEntity before saving newEntity
  2. Use session.merge() on oldEntity to replace the version in the session cache (newEntity) with the original (oldEntity)

EDIT: to elaborate a little, the problem here is that Hibernate keeps a persistence context, which is the objects being monitored as part of each session. You can't do update() on a detached object (one not in the context) while there's an attached object in the context. This should work:

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

and so should this:

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



回答2:


What about using session.isDirty()? The JavaDoc says that method will answer the question "Would any SQL be executed if we flushed this session?" Of course, that would only work if you had a new clean Session to start with. Another option - just use two different Sessions.



来源:https://stackoverflow.com/questions/183013/hibernate-comparing-current-previous-record

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!