休眠。什么时候同一个实体可以在一个会话中加载两次?

时间:2013-12-16 08:44:14

标签: java hibernate

有这样的问题。加载2个对象的集合(通过主键,使用标准)。然后在循环中迭代它们。处理第一个对象时,距离此循环非常远的地方,是由与循环中的第二个对象相同的主键加载对象。在这里,我看到System.identityHashCode()对于这2个对象是不同的。当从循环处理第二个对象并尝试保存它时,我得到异常:

org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:

尝试用简单的对象模拟这个问题,加载,修改,再次通过PK加载,保存不同的事务传播-s我总是得到相同的对象实例... 你能告诉我什么时候可以通过PK在同一个会话加载中获得第二个对象实例吗?

2 个答案:

答案 0 :(得分:4)

在我的情况下问题是因为: 首先,我已经通过主键加载了一些实体'A'。 然后我使用一些标准加载了另一个实体'B',这些标准通过 hbm 映射引用了相同的(通过PK)实体'A'(例如B->某个实体C-> A)和hibernate没有使用已经加载的'A'实体,但是后来加载或创建它(我在实体'A'构造函数中放置了断点),因此在单个会话中我们有2个具有相同PK但不同实例的实体。试图保存实体'A'我们得到异常'NonUniqueObjectException'。 加载实体'B'在某种程度上非常遥远,并且在某些条件下可以重现并识别问题。 要更快地找到这些地方,请在“NonUniqueObject”构造函数中放置断点,并找到第二次加载此实体的人。 顺便说一句,在我加载实体'B'后,我没有尝试调用B-> C-> A,lazy ='proxy'或者根本没有lazy,这意味着每个请求加载C.我的一些谜......

答案 1 :(得分:0)

使用单个主键字段实现equals()和hashcode()的简单方法,比如说String或者Integer就是这样:

public boolean equals(Object obj) {
   if (obj == null) { return false; }
   if (obj == this) { return true; }
   if (obj.getClass() != getClass()) {
     return false;
   }
   ThisClass that = (ThisClass) obj;
   return this.id.equals( that.id );
}
public int hashCode() {
    returns id.hashCode();
}

对于复合键,您将要使用这样的代码:

http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/builder/HashCodeBuilder.html

http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/builder/EqualsBuilder.html