Sí, esto es posible. Este es un caso especial de la relación estándar bidireccional @ManyToOne
/@OneToMany
. Es especial porque la entidad en cada extremo de la relación es la misma. El caso general se detalla en la Sección 2.10.2 del JPA 2.0 spec.
Aquí hay un ejemplo trabajado. En primer lugar, la clase de entidad 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...
}
He aquí un método main()
áspera que persiste tres de estas entidades:
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();
}
En este caso, las tres instancias de la entidad deben ser persistieron antes de confirmar la transacción. Si no puedo persistir en una de las entidades en el gráfico de las relaciones padre-hijo, se genera una excepción en commit()
. En Eclipselink, este es un RollbackException
que detalla la incoherencia.
Este comportamiento se puede configurar a través del atributo cascade
en A
's @OneToMany
y @ManyToOne
anotaciones. Por ejemplo, si configuro cascade=CascadeType.ALL
en ambas anotaciones, podría persistir de forma segura una de las entidades e ignorar las demás. Digamos que persistí parent
en mi transacción. La implementación de JPA atraviesa la propiedad parent
de children
porque está marcada con CascadeType.ALL
. La implementación de JPA encuentra allí son
y daughter
. Luego persiste a ambos niños en mi nombre, aunque no lo solicité explícitamente.
Una nota más. Siempre es responsabilidad del programador actualizar ambos lados de una relación bidireccional. En otras palabras, cada vez que agrego un hijo a algún padre, debo actualizar la propiedad principal del hijo en consecuencia. Actualizar solo un lado de una relación bidireccional es un error bajo JPA. Siempre actualice ambos lados de la relación. Esto está escrito de forma inequívoca en la página 42 de la APP 2.0 especificaciones:
en cuenta que es la aplicación que tiene la responsabilidad de mantener la consistencia de tiempo de ejecución de las relaciones, por ejemplo, para asegurar que el “uno” y los “muchos "Los lados de una relación bidireccional son consistentes entre sí cuando la aplicación actualiza la relación en tiempo de ejecución.
¡Muchas gracias por la explicación detallada!El ejemplo es al grano y funcionó en la primera ejecución. – sanjayav
@sunnyj Me alegra ayudar. Buena suerte con tus proyectos). –
Se encontró con este problema antes al crear entidad de categoría que tiene subcategorías. ¡Es útil! –