java jpa jpa-1.0

java - JPA OneToMany no elimina al niño



jpa-1.0 (7)

Además de la respuesta de cletus, JPA 2.0 , final desde diciembre de 2010, introduce un atributo @OneToMany en @OneToMany anotaciones. Para más detalles, mira esta entrada de blog .

Tenga en cuenta que dado que la especificación es relativamente nueva, no todos los proveedores de JPA 1 tienen una implementación final de JPA 2. Por ejemplo, la versión Hibernate 3.5.0-Beta-2 aún no es compatible con este atributo.

Tengo un problema con una asignación simple de @OneToMany entre una entidad principal y una secundaria. Todo funciona bien, solo que los registros secundarios no se eliminan cuando los elimino de la colección.

El padre:

@Entity public class Parent { @Id @Column(name = "ID") private Long id; @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "parent") private Set<Child> childs = new HashSet<Child>(); ... }

El niño:

@Entity public class Child { @Id @Column(name = "ID") private Long id; @ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name="PARENTID", nullable = false) private Parent parent; ... }

Si ahora elimino y el elemento secundario del conjunto de elementos secundarios, no se elimina de la base de datos. Intenté anular la referencia de child.parent , pero tampoco funcionó.

Las entidades se utilizan en una aplicación web, la eliminación ocurre como parte de una solicitud Ajax. No tengo una lista de hijos eliminados cuando se presiona el botón Guardar, por lo que no puedo eliminarlos implícitamente.


Aquí en cascada, en el contexto de eliminar, significa que se eliminan los hijos si quita el padre. No es la asociación Si está utilizando Hibernate como su proveedor de JPA, puede hacerlo utilizando una cascada específica de hibernación .


Como se explicó, no es posible hacer lo que quiero con JPA, así que empleé la anotación hibernate.cascade, con esto, el código relevante en la clase Parent ahora se ve así:

@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, mappedBy = "parent") @Cascade({org.hibernate.annotations.CascadeType.SAVE_UPDATE, org.hibernate.annotations.CascadeType.DELETE, org.hibernate.annotations.CascadeType.MERGE, org.hibernate.annotations.CascadeType.PERSIST, org.hibernate.annotations.CascadeType.DELETE_ORPHAN}) private Set<Child> childs = new HashSet<Child>();

No pude usar simplemente ''TODO'', ya que esto también habría eliminado al padre.


El comportamiento de JPA es correcto (es decir , según la especificación ): los objetos no se eliminan simplemente porque los eliminó de una colección de OneToMany. Existen extensiones específicas de proveedores que hacen eso pero el JPA nativo no lo satisface.

En parte esto se debe a que JPA no sabe realmente si debe eliminar algo eliminado de la colección. En términos de modelado de objetos, esta es la diferencia entre composición y "agregación *.

En composición , la entidad hijo no tiene existencia sin el padre. Un ejemplo clásico es entre Casa y Habitación. Eliminar la casa y las habitaciones también.

La agregación es un tipo de asociación más flexible y está tipificada por Curso y Estudiante. Eliminar el curso y el alumno todavía existe (probablemente en otros cursos).

Por lo tanto, necesita usar extensiones específicas del proveedor para forzar este comportamiento (si está disponible) o eliminar explícitamente al niño Y eliminarlo de la colección principal.

Soy consciente de:


Puedes intentar esto:

@OneToOne(orphanRemoval=true) or @OneToMany(orphanRemoval=true) .


Puedes intentar esto:

@OneToOne(cascade = CascadeType.REFRESH)

o

@OneToMany(cascade = CascadeType.REFRESH)


@Entity class Employee { @OneToOne(orphanRemoval=true) private Address address; }

Mira here .