什么时候hibernate从内存中删除分离的对象NonUniqueObjectException

时间:2016-05-12 10:30:55

标签: java hibernate jpa

我理解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中删除所有对象。

2 个答案:

答案 0 :(得分:2)

Hibernate确实保持对分离对象的引用,即分离的对象不是任何会话的一部分,并且它们的垃圾收集不会受到任何阻碍。

NonUniqueObjectException的原因是同一数据库行的两个不同对象已与同一会话关联。这很糟糕,因为Hibernate会自动检测会话中对象的更改,并将这些更改写回数据库。如果同一行的多个对象在同一会话中,则应该写入对象的状态是不明确的。因为这会导致很难找到错误,所以Hibernate拒绝这种情况。

通常,Hibernate确保给定会话中某行的所有查询都返回相同的对象,因此不会出现这种情况。但是,如果您使用从具有新会话的其他会话获取的对象,它将与新会话关联,如果新会话已包含该行的对象,则该会话可能会失败。

这就是为什么较新的EntityManager API不再具有update方法的原因,该方法将预先存在的对象与会话相关联,而merge方法将对象的内容复制到与会话相关联的对象。

答案 1 :(得分:1)

要理解,请看一下:

http://3.bp.blogspot.com/-katvFbmjewU/Tqv4Ble7_QI/AAAAAAAAAJE/odH15Qm9-hs/s1600/object-states.JPG

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