Sì, questo è possibile. Questo è un caso speciale della relazione bidirezionale standard @ManyToOne
/@OneToMany
. È speciale perché l'entità su ciascuna estremità della relazione è la stessa. Il caso generale è dettagliato nella sezione 2.10.2 dello JPA 2.0 spec.
Ecco un esempio funzionante. In primo luogo, la classe 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...
}
Ecco un metodo di massima main()
che persiste tre tali entità:
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();
}
In questo caso, tutte e tre le istanze di entità devono essere persistenti prima transazione commesso. Se non riesco a mantenere una delle entità nel grafico delle relazioni genitore-figlio, viene generata un'eccezione su commit()
. Su Eclipselink, questo è un RollbackException
che dettaglia l'inconsistenza.
Questo comportamento è configurabile tramite l'attributo cascade
nelle annotazioni @OneToMany
e @ManyToOne
A
. Ad esempio, se imposto cascade=CascadeType.ALL
in entrambe le annotazioni, posso tranquillamente mantenere una delle entità e ignorare le altre. Dite che ho persistito parent
nella mia transazione. L'implementazione JPA attraversa la proprietà perché è contrassegnata con CascadeType.ALL
. L'implementazione JPA trova son
e daughter
lì. Quindi persiste entrambi i bambini a mio nome, anche se non l'ho richiesto esplicitamente.
Un'altra nota. È sempre responsabilità del programmatore aggiornare entrambi i lati di una relazione bidirezionale. In altre parole, ogni volta che aggiungo un figlio a un genitore, devo aggiornare di conseguenza la proprietà genitore del bambino. L'aggiornamento di un solo lato di una relazione bidirezionale è un errore in JPA. Aggiorna sempre entrambi i lati della relazione. Questo è scritto in modo inequivocabile a pagina 42 delle specifiche JPA 2.0:
Si noti che è l'applicazione che ha la responsabilità di mantenere la coerenza di runtime rapporti, ad esempio, per assicurare che “uno” e “molti "I lati di una relazione bidirezionale sono coerenti l'uno con l'altro quando l'applicazione aggiorna la relazione in fase di runtime.
Grazie mille per la spiegazione dettagliata!L'esempio è al punto e ha funzionato nella prima esecuzione. – sanjayav
@sunnyj Felice di aiutare. Buona fortuna con i tuoi progetti). –
Ha incontrato questo problema prima durante la creazione di un'entità di categoria con sottocategorie. È utile! –