javax.persistence.EntityExistsException:具有相同标识符值的其他对象已与会话关联

时间:2013-08-27 12:25:11

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

我有两个实体(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:具有相同标识符值的另一个对象已与会话关联“。我不知道如何解决这个问题。该消息清楚地表明,hibernate会话发现了重复的条目(这是因为compositekey具有默认由MyEclipse生成的覆盖方法,它生成相同的哈希码,但我不确定这是否会导致问题)。请告诉我如何解决这个问题。是否需要覆盖compositekey类中的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;
}

1 个答案:

答案 0 :(得分:1)

我认为您的问题可能与根据JPA / EJB3.1的hashCode / Equals与对象标识不对应有关。

尝试将hashCode / Equals方法添加到B中,并将该bEntities更改为List - 或者如果将其保留为set,则确保hashCode / Equals在添加到set之前使用的数据是水合的。您应该通过将hashCode和equals方法添加到CompositeKey并在B的hashcode和equals中对它们进行处理来实现此目的。

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