【问题标题】:Hibernate: comparing current & previous recordHibernate:比较当前和以前的记录
【发布时间】:2010-09-16 00:42:54
【问题描述】:

我想将内存中 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 注释时挂起... :-(

【问题讨论】:

    标签: hibernate jpa session diff


    【解决方案1】:

    使用 session.isDirty() 怎么样? JavaDoc 说该方法将回答“如果我们刷新此会话,是否会执行任何 SQL?”这个问题。当然,这只有在你有一个新的干净会话开始时才有效。另一种选择 - 只需使用两个不同的会话。

    【讨论】:

      【解决方案2】:

      想到两个简单的选择:

      1. 在保存 newEntity 之前驱逐 oldEntity
      2. 在 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
      

      【讨论】:

      • 您能详细说明一下吗?我都试过了,但都没有成功……也许我做错了
      • 我用策略 #2 做到了,tnx
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-07
      • 2014-10-18
      • 1970-01-01
      • 2017-11-25
      • 1970-01-01
      相关资源
      最近更新 更多