Hibernate insère les doublons dans un @OneToMany collection

J'ai une question concernant Hibernate 3.6.7 et JPA 2.0.

Envisager des entités suivantes (certains getters et les setters sont omis par souci de concision):

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

Considérons maintenant ce morceau de code:

//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()); //-> [Child@1, Child@1]

em.getTransaction().commit();
em.close();

L'entité enfant est mal inséré deux fois dans la liste des enfants de l'entité mère.

Lorsque vous effectuez l'une des opérations suivantes, le code fonctionne très bien (pas de doublons dans la liste):

  • supprimer la mappedBy attribut dans l'entité mère
  • effectuer certaines opérations de lecture de sur la liste des enfants (par exemple, décommentez la ligne marquée par *)

Ceci est bien évidemment un comportement bizarre. Aussi, lors de l'utilisation de EclipseLink comme le fournisseur de persistance, le code fonctionne comme prévu (pas de doublons).

Est-ce une Hibernate bug ou ai-je raté quelque chose?

Grâce

  • Pourriez-vous ajouter le code de la setParent de la méthode et de l'est égal à/hashCode méthodes?
  • Je viens d'ajouter les méthodes que vous avez demandé. Cependant, je ne pense pas que ce problème est lié à égale / hashCode.
  • Vos égaux méthodes ne respectent pas le contrat de l'Objet.d'égal à égal. En outre, le hashCode changements lorsque l'ID est généré et attribué à l'entité. Je ne serais pas surpris si le bug a disparu une fois que vous retirez hashCode et equals. BTW. Hibernate ne recommande pas l'utilisation de l'ID d'implémenter equals et hashCode.
  • Merci pour votre commentaire. Je n'étais pas au courant de la controverse de l'aide de l'identifiant persistant dans equals et hashCode. Mais même si j'ai supprimer mon equals et hashCode implémentations, le problème reste le même.
InformationsquelleAutor user1014562 | 2011-10-26