hibernate错误:具有相同标识符值的不同对象已经与会话相关联

我基本上在这个configuration中有一些对象(真正的数据模型有点复杂):

  • A与B有多对多的关系(B有inverse="true"
  • B与C有着多对一的关系(我把cascade设置为"save-update"
  • C是一种types/类别表。

另外,我应该提到主键是由数据库在保存时生成的。

有了我的数据,我有时会遇到A有一组不同的B对象的问题,这些B对象引用同一个C对象。

当我调用session.saveOrUpdate(myAObject) ,我得到一个hibernate错误,说: "a different object with the same identifier value was already associated with the session: C" 。 我知道hibernate不能在同一个会话中插入/更新/删除同一个对象两次,但是有没有办法解决这个问题呢? 这似乎不是那种罕见的情况。

在我研究这个问题的时候,我已经看到人们使用session.merge() ,但是当我这样做的时候,任何“冲突的”对象都被作为空白对象插入到数据库中,所有的值都设置为null。 显然这不是我们想要的。

另外一个我忘记提到的是(由于体系结构的原因,我无法控制),每个读或写需要在一个单独的会话中完成。

很可能是因为B对象不是指同一个Java C对象实例。 他们指的是数据库中的同一行(即相同的主键),但它们是不同的副本。

所以发生的事情是,pipe理实体的Hibernate会话将跟踪哪个Java对象与具有相同主键的行相对应。

一种select是确保引用同一行的对象B的实体实际上是指C的同一对象实例。或者closures该成员variables的级联。 当B坚持时,这种方式不是C。 不过,您将不得不手动保存C. 如果C是一个types/类别表,那么这样做可能是有道理的。

只要设置级联MERGE,这应该做的伎俩。

通过使用以下命令将对象ID从Hibernate分配给数据库的任务:

 <generator class="native"/> 

这解决了我的问题。

你只需要做一件事。 运行session_object.clear() ,然后保存新的对象。 这将清除会话(如适当命名),并从会话中删除违规的重复对象。

解决上述问题的一种方法是重写hashcode()
同时在保存之前和之后刷新hibernate会话。

 getHibernateTemplate().flush(); 

显式设置分离的对象为null也有帮助。

刚刚遇到这个消息,但在C#代码。 不知道是否相关(尽pipe相同的错误信息)。

我正在用断点debugging代码,并在debugging器处于断点处时通过私有成员扩展某些集合。 重新运行代码而不挖掘结构使错误消息消失。 看起来,查看私有惰性加载集合的行为使NHibernate加载了当时不应该加载的东西(因为它们在私有成员中)。

代码本身包装在一个相当复杂的事务中,可以更新大量logging和许多依赖项作为该事务的一部分(导入过程)。

希望能够给遇到问题的任何人提供线索。

我同意@Hemant kumar,谢谢你差别很大。 根据他的解决scheme,我解决了我的问题。

例如:

 @Test public void testSavePerson() { try (Session session = sessionFactory.openSession()) { Transaction tx = session.beginTransaction(); Person person1 = new Person(); Person person2 = new Person(); person1.setName("222"); person2.setName("111"); session.save(person1); session.save(person2); tx.commit(); } } 

Person.java

 public class Person { private int id; private String name; @Id @Column(name = "id") public int getId() { return id; } public void setId(int id) { this.id = id; } @Basic @Column(name = "name") public String getName() { return name; } public void setName(String name) { this.name = name; } } 

这个代码总是在我的应用程序中出错: A different object with the same identifier value was already associated with the session ,后来,我发现我自动增加了我的主键!

我的解决scheme是将此代码添加到您的主键:

 @GeneratedValue(strategy = GenerationType.AUTO) 

将注释@GeneratedValue添加到要插入的bean。

我有这个错误几天一去,我花了太多的时间来修复这个错误。

  public boolean save(OrderHeader header) { Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); try { session.save(header); for (OrderDetail detail : header.getDetails()) { session.save(detail); } transaction.commit(); session.close(); return true; } catch (HibernateException exception) { exception.printStackTrace(); transaction.rollback(); return false; } } 

在我得到这个错误之前,我没有提到OrderDetil对象的ID生成types。 当没有生成Orderdetails的id时,它将每个OrderDetail对象的Id保持为0。 这是什么#jbx解释。 是的,这是最好的答案。 这一个例子是如何发生的。

尝试放置您的查询的代码之前。 这解决了我的问题。 例如改变这个:

 query1 query2 - get the error update 

对此:

 query2 query1 update 

在Hibernate中查找“Cascade”属性并删除它。 当你设置“Cascade”可用时,它将调用其他与相关类关联的实体的其他操作(保存,更新和删除)。 所以相同的身份价值将会发生。 它与我合作。

在调用更新查询之前,您可能不会设置对象的标识符。