Pregunta

Tengo un problema con un mapeo @OneToMany simple entre un padre y una entidad secundaria. Todo funciona bien, sólo que los registros secundarios no se eliminan cuando les quitar 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 borro y el niño desde el conjunto del niño, no se borran de la base de datos. He intentado anular la referencia child.parent, pero eso tampoco funcionó.

Las entidades se utilizan en una aplicación web, la eliminación ocurre como parte de una petición Ajax. No tengo una lista de borrados del niño cuando se pulsa el botón de guardar, así que no puedo eliminarlos de forma implícita.

¿Fue útil?

Solución

El comportamiento de la APP es correcta (lo que significa según la especificación ): los objetos no se eliminan simplemente porque les has quitado de una colección OneToMany. Existen extensiones específicas del proveedor que hacen eso, pero APP nativa no está pensado para ello.

En parte, esto se debe a que la APP en realidad no sabe si debe borrar algo retirado de la colección. En términos de modelado de objetos, esta es la diferencia entre el composición y "agregación *.

composición , la entidad niño no tiene existencia sin el padre. Un ejemplo clásico es de entre casa y la habitación. Eliminar la Cámara y las habitaciones van demasiado.

Agregación es un tipo más flexible de asociación y se caracteriza por curso y alumno. Eliminar el Curso y todavía existe Student (probablemente en otros cursos).

Por lo que necesita para cualquiera que use extensiones específicas del proveedor para forzar este comportamiento (si está disponible) o eliminar explícitamente el niño y sacarlo de la colección de los padres.

Soy consciente de:

Otros consejos

Además de la respuesta de Cletus, JPA 2.0 , definitiva desde December 2010 , introduce un atributo orphanRemoval en anotaciones @OneToMany. Para más detalles ver este entrada .

Tenga en cuenta que, dado que la especificación es relativamente nuevo, no todo proveedor JPA 1 tiene un final de ejecución de la APP 2. Por ejemplo, el Hibernate 3.5.0-Beta-2 de liberación aun no soporta este atributo.

Puede intentar esto:

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

Como se ha explicado, no es posible hacer lo que quiera con la APP, así que emplea la anotación hibernate.cascade, con esto, el código correspondiente en la clase padre 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 se pudo usar simple 'ALL' ya que esto habría eliminado el padre también.

A continuación, en cascada, en el contexto de quitar, significa que los niños se eliminan si se quita el padre. No es la asociación. Si está usando Hibernate como su proveedor de JPA, puede hacerlo utilizando hibernar específica cascada .

Puede intentar esto:

@OneToOne(cascade = CascadeType.REFRESH) 

o

@OneToMany(cascade = CascadeType.REFRESH)
@Entity 
class Employee {
     @OneToOne(orphanRemoval=true)
     private Address address;
}

aquí .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top