Hibernate:比较当前和之前的纪录 [英] Hibernate: comparing current & previous record

查看:21
本文介绍了Hibernate:比较当前和之前的纪录的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

CODEBLOCK#1 中,我得到了 newEntity.getProperty()="new value" AND oldEntity.getProperty()="new value"代码>(当然,我期望的是 oldEntity.getProperty()="old value").实际上这两个对象在内存中是完全一样的.

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.

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

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

现在这两个实体是不同的,但当然我得到了可怕的org.hibernate.NonUniqueObjectException:具有相同标识符值的不同对象已经与会话相关联.

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.

有什么想法吗?

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

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

我的单元测试在尝试打印 oldEntity 笔记时挂起... :-(

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

推荐答案

两个简单的选项浮现在脑海中:

Two easy options spring to mind:

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

EDIT:详细说明一下,这里的问题是 Hibernate 保持一个持久化上下文,它是作为每个会话的一部分被监视的对象.当上下文中有附加对象时,您不能对分离的对象(不在上下文中的对象)执行 update().这应该有效:

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

所以应该这样做:

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

这篇关于Hibernate:比较当前和之前的纪录的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆