JPA CascadeType.ALL no elimina a los huérfanos


132

Tengo problemas para eliminar nodos huérfanos usando JPA con la siguiente asignación

@OneToMany (cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "owner")
private List<Bikes> bikes;

Tengo el problema de los roles huérfanos en la base de datos.

Puedo usar la org.hibernate.annotations.Cascadeetiqueta específica de anotación Hibernate, pero obviamente no quiero vincular mi solución a una implementación de Hibernate.

EDITAR : Parece que JPA 2.0 incluirá soporte para esto.

Respuestas:


164

Si lo está utilizando con Hibernate, tendrá que definir explícitamente la anotación CascadeType.DELETE_ORPHAN, que se puede usar junto con JPA CascadeType.ALL.

Si no planea usar Hibernate, primero deberá eliminar explícitamente los elementos secundarios y luego eliminar el registro principal para evitar registros huérfanos.

secuencia de ejecución

  1. buscar la fila principal que se eliminará
  2. buscar elementos secundarios
  3. eliminar todos los elementos secundarios
  4. eliminar fila principal
  5. Cerrar la sesión

Con JPA 2.0, ahora puede usar la opción orphanRemoval = true

@OneToMany(mappedBy="foo", orphanRemoval=true)

3
gracias terminé yendo por esta ruta, creo que esto es un poco exagerado para la especificación JPA.
Paul Whelan

13
El estándar JPA 2.0 ahora tiene deleteOrphan como un atributo de @OneToMany Si está utilizando la última hibernación, puede hacer @OneToMany (..., deleteOrphan = true)
jomohke

¿Qué es la secuencia de ejecución cuando solo actualizo elementos secundarios? ¿Se eliminarán los registros huérfanos?
jAckOdE

113

Si está utilizando JPA 2.0, ahora puede usar el orphanRemoval=trueatributo de la @xxxToManyanotación para eliminar a los huérfanos.

En realidad, CascadeType.DELETE_ORPHANha quedado en desuso en 3.5.2-Final.


66
En realidad, creo que orphanRemoval = true significa algo más, es decir, eliminar un objeto cuando lo elimino de la colección de sus padres. Ver download.oracle.com/javaee/6/tutorial/doc/bnbqa.html#giqxy
Archie

Por favor, g a través del enlace de Archie.
Jigar Shah

44
orphanRemoval = true tampoco funciona. Tiene que hacerse a la antigua usanza.
Joe Almore

45
╔═════════════╦═════════════════════╦═════════════════════╗
   Action      orphanRemoval=true    CascadeType.ALL   
╠═════════════╬═════════════════════╬═════════════════════╣
   delete         deletes parent      deletes parent   
   parent         and orphans         and orphans      
╠═════════════╬═════════════════════╬═════════════════════╣
   change                                              
  children      deletes orphans         nothing        
    list                                               
╚═════════════╩═════════════════════╩═════════════════════╝

1
¿Qué sucede si tengo cascade = CascadeType.ALL, orphanRemoval = falsey elimino al padre? ¿Eliminará a los niños, aunque específicamente le dije que NO lo haga?
izogfif


7

puedes usar @PrivateOwned para eliminar huérfanos, por ejemplo

@OneToMany(mappedBy = "masterData", cascade = {
        CascadeType.ALL })
@PrivateOwned
private List<Data> dataList;

55
Gracias @reshma hay que tener en cuenta que @PrivateOwned es una extensión JPA eclipselink.
Paul Whelan

5

Acabo de encontrar esta solución, pero en mi caso no funciona:

@OneToMany(cascade = CascadeType.ALL, targetEntity = MyClass.class, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true) 

orphanRemoval = true no tiene ningún efecto.


1
Necesitaba limpiar y construir antes de que el cambio entrara en vigencia.
maralbjo

Wow, he estado buscando durante una hora por qué agregar CascadeType.ALL en mi ManyToOne no eliminaba en cascada. Limpiado y construido y funciona. Gracias @maralbjo.
Andrew Mairose


2

Tuve el mismo problema y me preguntaba por qué esta condición a continuación no eliminó a los huérfanos. La lista de platos no se eliminó en Hibernate (5.0.3.Final) cuando ejecuté una consulta de eliminación con nombre:

@OneToMany(mappedBy = "menuPlan", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Dish> dishes = new ArrayList<>();

Entonces recordé que no debo usar una consulta de eliminación con nombre , sino el EntityManager. Como utilicé el EntityManager.find(...)método para obtener la entidad y luego EntityManager.remove(...)eliminarla, los platos también se eliminaron.


2

Justo @OneToMany(cascade = CascadeType.ALL, mappedBy = "xxx", fetch = FetchType.LAZY, orphanRemoval = true).

Eliminar targetEntity = MyClass.class , funciona muy bien.



0

Estaba usando el mapeo uno a uno, pero el niño no estaba siendo eliminado JPA estaba infringiendo una clave foránea

Después de usar orphanRemoval = true, el problema se resolvió


@OneToOne (cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn (name = "CHILD_OID") niño privado;
vipin chauhan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.