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.

Paul Whelan
fuente

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)
Varun Mehta
fuente
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.

Kango_V
fuente
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                                               
╚═════════════╩═════════════════════╩═════════════════════╝
Sergii Shevchyk
fuente
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;
reshma
fuente
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.

Valéry Stroeder
fuente
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
4

Según Java Persistence with Hibernate , la eliminación huérfana en cascada no está disponible como una anotación JPA.

Tampoco es compatible con JPA XML.

kit de herramientas
fuente
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.

Bevor
fuente
2

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

Eliminar targetEntity = MyClass.class , funciona muy bien.

Kohan95
fuente
1

Para los registros, en OpenJPA antes de JPA2 era @ElementDependant.

Simone Gianni
fuente
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ó

vipin chauhan
fuente
@OneToOne (cascade = CascadeType.ALL, orphanRemoval = true) @JoinColumn (name = "CHILD_OID") niño privado;
vipin chauhan