Ho una domanda riguardante Hibernate 3.6.7 e JPA 2.0.Hibernate inserisce i duplicati in una raccolta @OneToMany
Considerare (alcuni getter e setter sono omessi per brevità) seguenti entità:
@Entity
public class Parent {
@Id
@GeneratedValue
private int id;
@OneToMany(mappedBy="parent")
private List<Child> children = new LinkedList<Child>();
@Override
public boolean equals(Object obj) {
return id == ((Parent)obj).id;
}
@Override
public int hashCode() {
return id;
}
}
@Entity
public class Child {
@Id
@GeneratedValue
private int id;
@ManyToOne
private Parent parent;
public void setParent(Parent parent) {
this.parent = parent;
}
@Override
public boolean equals(Object obj) {
return id == ((Child)obj).id;
}
@Override
public int hashCode() {
return id;
}
}
Ora considerare questo pezzo di codice:
// persist parent entity in a transaction
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Parent parent = new Parent();
em.persist(parent);
int id = parent.getId();
em.getTransaction().commit();
em.close();
// relate and persist child entity in a new transaction
em = emf.createEntityManager();
em.getTransaction().begin();
parent = em.find(Parent.class, id);
// *: parent.getChildren().size();
Child child = new Child();
child.setParent(parent);
parent.getChildren().add(child);
em.persist(child);
System.out.println(parent.getChildren()); // -> [[email protected], [email protected]]
em.getTransaction().commit();
em.close();
è erroneamente viene inserito l'un'entità figlio due volte nella lista di bambini dell'entità genitore.
Quando si esegue uno dei seguenti, il codice funziona bene (non le voci duplicate nella lista):
- rimuovere l'attributo
mappedBy
nella controllante - eseguire qualche operazione di lettura sulla lista dei figli (per esempio linea di commento contrassegnata da
*
)
Questo è ovviamente un comportamento molto strano. Inoltre, quando si utilizza EclipseLink come provider di persistenza, il codice funziona esattamente come previsto (nessun duplicato).
È un errore Hibernate o mi manca qualcosa?
Grazie
Potrebbe aggiungere il codice del metodo setParent e degli Eguali/metodi hashCode? –
Ho appena aggiunto i metodi che hai richiesto. Tuttavia, non penso che questo problema sia correlato a equals/hashCode. – user1014562
I tuoi metodi di uguale non rispettano il contratto di Object.equals. Inoltre, l'hashCode cambia quando l'ID viene generato e assegnato all'entità. Non sarei sorpreso se il bug scomparisse dopo aver rimosso hashCode e uguale. BTW. Hibernate consiglia di non utilizzare ID per implementare equals e hashCode. –