我想将内存中的Hibernate实体的当前值与数据库中的值进行比较:

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


在CODEBLOCK#1中,我得到了newEntity.getProperty()="new value"oldEntity.getProperty()="new value"(当然,我当然期望oldEntity.getProperty()="old value")。实际上,这两个对象在内存中完全相同。

我弄乱了HibernateSessionFactory.getSession().evict(newEntity)并尝试设置oldEntity=null摆脱它(我只需要它用于比较):

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


现在这两个实体是不同的,但是我当然得到了可怕的org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session

任何想法?

编辑:我尝试了双会话策略;我修改了我的HibernateSessionFactory以实现会话映射,然后...

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


尝试打印oldEntity注释时,我的单元测试挂起... :-(

最佳答案

我想到两个简单的选择:


保存newEntity之前逐出oldEntity
在oldEntity上使用session.merge()将会话缓存(newEntity)中的版本替换为原始(oldEntity)


编辑:详细说明一下,这里的问题是Hibernate保留了一个持久性上下文,这是作为每个会话的一部分进行监视的对象。当上下文中有一个附加对象时,您不能对一个分离的对象(不在上下文中的对象)执行update()。这应该工作:

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


所以应该这样:

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

10-06 01:37