代码之家  ›  专栏  ›  技术社区  ›  Manrico Corazzi

休眠:比较当前和以前的记录

  •  3
  • Manrico Corazzi  · 技术社区  · 18 年前

    我想将内存中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);    
    

    在里面 代码块#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);
    

    我的单元测试在尝试打印旧实体注释时挂起…:-(

    2 回复  |  直到 5 年前
        1
  •  7
  •   Cowan    18 年前

    我想到了两个简单的选择:

    1. 在保存新实体之前逐出旧实体

    编辑 :更详细地说,这里的问题是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
  •  0
  •   Brian Deterling    18 年前

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

    推荐文章