简体   繁体   中英

javax.persistence.EntityExistsException: a different object with the same identifier value was already associated with the session

I have two entities (A & B). A has one to many relation with the entity B. Primary key of the entity A is auto increment where as the primary key of entity B is composite (consisting of PK of entity A as a foreign key and one auto incremented id).

Note: I am using EJB 3.1 with MySQL, Jboss7

I populate the entity A from my business objects and create it in the following way.

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);

Whenever I pass one object of Entity B in the bEntities list then the program works as expected all the fields in the database are populated correctly but when i add more than one object entity B in the bEntities list then I get the exception "javax.persistence.EntityExistsException: a different object with the same identifier value was already associated with the session". I am not sure how to work around this one. The message clearly says that the hibernate session has found duplicate entries (which is due to the fact that compositekey has overriden methods generated by default by MyEclipse which generates the same hashcode but I am not sure this is causing the problem). Kindly tell me how can i solve this. Is there a need to override the equals and hashcode methods in the compositekey class? Thanks in advance.

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;
}

I think your issue may have something to do with how the hashCode/Equals does not correspond to the objects identity according to JPA/EJB3.1.

Try and add the hashCode/Equals methods to B and also change that bEntities to a List - or if you keep it a set then ensure that the data that hashCode/Equals uses before it is added to the set is hydrated. You should probably do this by adding hashCode and equals methods to CompositeKey and deffering to them in B's hashcode and equals.

Btw, you must add hashCode and Equals methods to CompositeKey. One of the reason for using a CompositeKey is to tell the persistence framework how to compare to composite keys.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM