Hibernate错误:org.hibernate.NonUniqueObjectException:具有相同标识符值的另一个对象已与会话关联

har*_*hit 104 java orm hibernate

我有两个用户对象,而我尝​​试使用保存对象

session.save(userObj);
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:
[com.pojo.rtrequests.User#com.pojo.rtrequests.User@d079b40b]
Run Code Online (Sandbox Code Playgroud)

我正在使用创建会话

BaseHibernateDAO dao = new BaseHibernateDAO();          

rtsession = dao.getSession(userData.getRegion(),
                           BaseHibernateDAO.RTREQUESTS_DATABASE_NAME);

rttrans = rtsession.beginTransaction();
rttrans.begin();

rtsession.save(userObj1);
rtsession.save(userObj2);

rtsession.flush();
rttrans.commit();

rtsession.close(); // in finally block
Run Code Online (Sandbox Code Playgroud)

我也尝试session.clear()过保存之前,仍然没有运气.

这是第一次我收到用户请求时获取会话对象,所以我得到的原因是说会话中存在该对象.

有什么建议?

Mic*_*les 168

我多次遇到这个错误,追踪很难......

基本上,hibernate所说的是你有两个具有相同标识符(相同主键)的对象,但它们不是同一个对象.

我建议你分解你的代码,即注释掉比特,直到错误消失,然后把代码放回去,直到它回来,你应该找到它的错误.

它通常通过级联保存发生,其中对象A和B之间存在级联保存,但是对象B已经与会话关联但不在同一个B实例上.

你使用什么主键生成器?

我问的原因是这个错误与你如何告诉hibernate确定一个对象的持久状态(即一个对象是否持久)有关.错误可能正在发生,因为hibernate试图持久化并且对象已经持久化.实际上,如果你使用save hibernate将尝试并持久保存该对象,并且可能已经存在与该会话相关联的相同主键的对象.

假设您有一个基于主键组合(第1列和第2列)的10行表的hibernate类对象.现在,您已经在某个时间点从表中删除了5行.现在,如果您尝试再次添加相同的10行,而hibernate尝试将对象保留在数据库中,则将添加已删除的5行而不会出现错误.现在剩下的5行已经存在,将抛出此异常.

因此,简单的方法是检查您是否更新/删除了表中的任何值,这是某些事情的一部分,之后您是否尝试再次插入相同的对象

  • 不错的答案².主键是我的问题,通过GeneratedValue为postgresql设置序列解决了. (3认同)
  • 我遇到过同样的问题。就我而言,我在代码中搜索了一个对象,我尝试在其他代码段中构建一个具有相同 ID 的新对象,而第一个对象还处于休眠状态。 (2认同)

小智 18

这只是hibernate解决问题的一个问题.在我的情况下,有许多具有相同标识符0的对象,因为它们是新的并且没有.db生成它们.在某处我读过0信号Id未设置.保持它们的直观方式是迭代它们并说hibernate来保存对象.但是你不能这样做 - "当然你应该知道hibernate可以这样工作,因此你必须......"所以现在我可以尝试将Ids改为Long而不是long,看看它是否有效.最后,您可以使用自己的简单映射器更容易地完成它,因为休眠只是一个额外的不明显负担.另一个例子:尝试从一个数据库中读取参数并将它们保存在另一个数据库中会强制您手动执行几乎所有工作.

  • 我讨厌hibernate ......和数据库......在他们引起我的所有问题之后我想我更容易使用文本文件(我在开玩笑,但仍然......). (12认同)

小智 16

使用session.evict(object);的函数evict()方法用于从会话缓存中删除实例.因此,首次保存对象时,session.save(object)在从缓存中逐出对象之前,通过调用方法来保存对象.以同样的方式通过调用session.saveOrUpdate(object)session.update(object)在调用evict()之前更新对象.


小智 10

当您使用相同的会话对象进行读写时,可能会发生这种情况.怎么样?假设您已创建一个会话.您使用主键Emp_id = 101从employee表中读取记录现在您已在Java中修改了记录.并且您将在数据库中保存Employee记录.我们这里没有关闭会议.由于读取的对象也会在会话中持续存在.它与我们希望编写的对象相冲突.因此出现了这个错误.


red*_*edi 8

正如上面已经指出的那样,当我cascade=all处于one-to-many关系的两端时,我遇到了这个问题,所以让我们假设A - > B(A中的一对多和B中的多对一)并且正在更新实例B在A中然后调用saveOrUpdate(A),它导致循环保存请求,即保存A触发保存B触发保存A ...而在第三个实例中,因为实体(A)被尝试添加到sessionPersistenceContext中引发了duplicateObject异常.
  我可以通过从一端删除级联来解决它.


小智 6

session.merge(obj)如果您使用具有相同标识符持久对象的不同会话进行保存,则可以使用, 。
它有效,我以前也遇到过同样的问题。


wbd*_*rby 5

我遇到了这个问题:

  1. 删除对象(使用 HQL)
  2. 立即存储具有相同 id 的新对象

我通过在删除后刷新结果并在保存新对象之前清除缓存来解决它

String delQuery = "DELETE FROM OasisNode";
session.createQuery( delQuery ).executeUpdate();
session.flush();
session.clear();
Run Code Online (Sandbox Code Playgroud)


小智 5

当我们更新会话的同一对象(我们使用该对象从数据库获取对象)时,就会出现此问题。

您可以使用hibernate的merge方法代替update方法。

例如,首先使用session.get(),然后可以使用session.merge(object)。这种方法不会产生任何问题。我们还可以使用 merge() 方法来更新数据库中的对象。