【问题标题】:javax.persistence.EntityExistsException: a different object with the same identifier value was already associated with the sessionjavax.persistence.EntityExistsException:具有相同标识符值的不同对象已与会话关联
【发布时间】:2013-08-30 04:43:45
【问题描述】:

我有两个实体(A 和 B)。 A 与实体 B 具有一对多关系。实体 A 的主键是自动递增的,而实体 B 的主键是复合的(由作为外键的实体 A 的 PK 和一个自动递增的 id 组成)。

注意:我正在使用 EJB 3.1 和 MySQL,Jboss7

我从我的业务对象中填充实体 A 并按以下方式创建它。

A a = new A();
Set<B> bEntitiesList = new HashSet<B>();
B b = new B();
b.setCompositeKey(new compositeKey()); // I am not setting any value in the 
// key and it will have null values for idA and idB.
// idB is null because it will be auto incremented in this table by MySQL
bEntitiesList.put(b);
a.setBEntities(bEntitiesList);
entityManager.persist(a);

每当我在 bEntities 列表中传递实体 B 的一个对象时,程序就会按预期工作,数据库中的所有字段都正确填充,但是当我在 bEntities 列表中添加多个对象实体 B 时,我会得到异常“ javax.persistence.EntityExistsException:具有相同标识符值的不同对象已与会话关联”。我不知道如何解决这个问题。该消息清楚地表明休眠会话已找到重复条目(这是由于 Compositekey 覆盖了 MyEclipse 默认生成的方法,该方法生成相同的哈希码,但我不确定这是导致问题的原因)。请告诉我如何解决这个问题。是否需要覆盖复合键类中的 equals 和 hashcode 方法?提前致谢。

public class A
{
    private Integer idA;
    private Set<B> bEntities = new HashSet<B>(0);
    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "A", unique = true, nullable = false)
    public Integer getIdA() {
      return this.idA;
    }
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "A")
    public Set<B> getBEntities() {
      return this.bEntities;
    }
}

public class B
{
    private compositeKey key;
    private A entityA;
    @EmbeddedId
    @AttributeOverrides({
    @AttributeOverride(name="idB",column=@Column(name="idB",nullable=false))})
    public compositeKey  getKey() {
       return this.key;
    }
    public void setKey(compositeKey key) {
      this.key = key;
    }
    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("providerReferenceNo")
    @JoinColumn(name = "idA", nullable = false, insertable = false, updatable = false)
    public A getEntityA() {
      return this.entityA;
    }
}


@Embeddable
public class compositeKey {
private Integer idA;
private Integer idB;

@GeneratedValue(strategy = IDENTITY)
@Column(name = "idB", nullable = false)
public Integer getIdB() {
  return this.idB;
}
@Column(name = "idA", nullable = false)
public Integer getIdA() {
  return this.idA;
}

【问题讨论】:

  • 谢谢 Micheal.. 我已经看过这个帖子了。我已经调试了应用程序,我发现每当我创建一个复合键对象时,它都会得到一个哈希码,比如说 ab871c,它被正确保存在数据库中,但是当我创建多个对象时;所有对象都获得相同的哈希码,即 ab871c。为什么我会出现这种行为?是因为compositeKey 中的两个字段都是空的吗?有解决办法吗?

标签: mysql hibernate jpa persistence composite-primary-key


【解决方案1】:

我认为您的问题可能与 hashCode/Equals 如何与 JPA/EJB3.1 中的对象身份不对应有关。

尝试将 hashCode/Equals 方法添加到 B 并将 bEntities 更改为 List - 或者如果您将其保留为一个集合,则确保 hashCode/Equals 在添加到集合之前使用的数据是水合的。您可能应该通过将 hashCode 和 equals 方法添加到 CompositeKey 并在 B 的 hashcode 和 equals 中区分它们来做到这一点。

顺便说一句,您必须将 hashCode 和 Equals 方法添加到 CompositeKey。使用 CompositeKey 的原因之一是告诉持久性框架如何与复合键进行比较。

【讨论】:

  • hashCode 和 equals 方法已经在 CompositeKey 类中被覆盖,但实现是默认的(在我生成实体和外观时由 MyEclipse 提供)。 “您可能应该通过将 hashCode 和 equals 方法添加到 CompositeKey 并在 B 的 hashcode 和 equals 中区分它们来做到这一点”是什么意思。就我个人而言,我认为 hashCode/equals 如何与 JPA/EJBs 3.1 中的对象身份相对应存在一个问题。我在哪里可以找到 JPA/EJB3.1 如何识别会话中的重复实体?标准是什么?
  • B 有 hashCode 和 Equals 吗?
  • 不,B 没有 hashCode & equals。
  • 更改hashCode方法,每次都生成随机数会不会是个好主意?你说什么?
猜你喜欢
  • 1970-01-01
  • 2012-09-07
  • 1970-01-01
  • 1970-01-01
  • 2014-04-16
  • 2021-09-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多