我理解NonUniqueObjectException何时发生以及为什么会发生。
我在网上看到很多关于NonUniqueObjectException的例子,每个都有相同的东西。 object首先从session1分离,因此session1也会被关闭并清除,然后具有相同标识符的对象是session2中的更新或SaveorUpdate。
代码段:
Session session = sessionFactory1.openSession();
Transaction tx = session.beginTransaction();
Item item = (Item) session.get(Item.class, new Long(1234));
tx.commit();
session.close(); // end of first session, item is detached
item.getId();// The database identity is "1234" item.setDescription("my new description");
Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction();
Item item2 = (Item) session2.get(Item.class, new Long(1234));
session2.update(item);// Throws NonUniqueObjectException
tx2.commit();
session2.close();
我的问题是即使seesion1已关闭,为什么hibernate会在session1中保留分离对象,但不管理它。何时从session1中删除所有对象。
答案 0 :(得分:2)
Hibernate确实不保持对分离对象的引用,即分离的对象不是任何会话的一部分,并且它们的垃圾收集不会受到任何阻碍。
NonUniqueObjectException的原因是同一数据库行的两个不同对象已与同一会话关联。这很糟糕,因为Hibernate会自动检测会话中对象的更改,并将这些更改写回数据库。如果同一行的多个对象在同一会话中,则应该写入对象的状态是不明确的。因为这会导致很难找到错误,所以Hibernate拒绝这种情况。
通常,Hibernate确保给定会话中某行的所有查询都返回相同的对象,因此不会出现这种情况。但是,如果您使用从具有新会话的其他会话获取的对象,它将与新会话关联,如果新会话已包含该行的对象,则该会话可能会失败。
这就是为什么较新的EntityManager API不再具有update
方法的原因,该方法将预先存在的对象与会话相关联,而merge
方法将对象的内容复制到与会话相关联的对象。
答案 1 :(得分:1)
要理解,请看一下:
Item item2 = (Item) session2.get(Item.class, new Long(1234));
这将在item2
中转为持久状态session2
,ID为1234。
session2.update(item);
item
处于分离状态,update()
将item
>>>上的session2
变为持久状态Hibernate抛出NonUniqueObjectException
,因为在同一个会话中有两个具有相同id的对象Item
!
这样做:
Session session2 = sessionFactory.openSession();
Transaction tx2 = session2.beginTransaction();
Item item2 = (Item) session2.get(Item.class, new Long(1234));
item2.setDescription("my new description");
session2.update(item2);
tx2.commit();