Oui, cela est possible. C'est un cas particulier de la relation bidirectionnelle standard @ManyToOne
/@OneToMany
. C'est spécial parce que l'entité à chaque extrémité de la relation est la même. Le cas général est détaillé à la section 2.10.2 du JPA 2.0 spec.
Voici un exemple travaillé. Tout d'abord, la classe d'entité A
:
@Entity
public class A implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
@ManyToOne
private A parent;
@OneToMany(mappedBy="parent")
private Collection<A> children;
// Getters, Setters, serialVersionUID, etc...
}
Voici une méthode main()
grossière qui persiste trois de ces entités:
public static void main(String[] args) {
EntityManager em = ... // from EntityManagerFactory, injection, etc.
em.getTransaction().begin();
A parent = new A();
A son = new A();
A daughter = new A();
son.setParent(parent);
daughter.setParent(parent);
parent.setChildren(Arrays.asList(son, daughter));
em.persist(parent);
em.persist(son);
em.persist(daughter);
em.getTransaction().commit();
}
Dans ce cas, doivent être conservées trois instances d'entités avant validation de la transaction. Si je ne parviens pas à persister une des entités dans le graphique des relations parent-enfant, une exception est lancée sur commit()
. Sur Eclipselink, il s'agit d'un RollbackException
détaillant l'incohérence.
Ce comportement est configurable via l'attribut cascade
sur les annotations @OneToMany
et @ManyToOne
de A
. Par exemple, si je mets cascade=CascadeType.ALL
sur ces deux annotations, je peux en toute sécurité persister une des entités et ignorer les autres. Dire que j'ai persisté parent
dans ma transaction. La mise en œuvre JPA traverse parent
children
car il est marqué CascadeType.ALL
. L'implémentation JPA trouve son
et daughter
là. Il persiste alors les deux enfants en mon nom, même si je ne l'ai pas explicitement demandé.
Une note de plus. Il est toujours de la responsabilité du programmeur de mettre à jour les deux côtés d'une relation bidirectionnelle. En d'autres termes, chaque fois que j'ajoute un enfant à un parent, je dois mettre à jour la propriété parent de l'enfant en conséquence. La mise à jour d'un seul côté d'une relation bidirectionnelle est une erreur sous JPA. Toujours mettre à jour les deux côtés de la relation. Ceci est écrit clairement à la page 42 de la spécification JPA 2.0:
Notez qu'il est l'application qui porte la responsabilité de maintenir la cohérence de runtime relations par exemple, pour assurer que le « un » et « beaucoup Les côtés d'une relation bidirectionnelle sont cohérents entre eux lorsque l'application met à jour la relation lors de l'exécution.
Merci beaucoup pour l'explication détaillée!L'exemple est au point et a travaillé dans la première manche. – sanjayav
@sunnyj Content de vous aider. Bonne chance avec votre projet (s). –
Il a déjà rencontré ce problème lors de la création d'une entité de catégorie avec des sous-catégories. C'est utile! –