JPA CascadeType.ALL no elimina a los huérfanos
Pregunta
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 etiqueta específica de anotación org.hibernate.annotations.Cascade
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.
Solución
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 utilizar Hibernate, primero deberá eliminar explícitamente los elementos secundarios y luego eliminar el registro principal para evitar cualquier registro huérfano.
secuencia de ejecución
- buscar la fila principal que se va a eliminar
- recuperar elementos secundarios
- eliminar todos los elementos secundarios
- eliminar fila principal
- cerrar sesión
Con JPA 2.0, ahora puede usar la opción orphanRemoval = true
@OneToMany(mappedBy="foo", orphanRemoval=true)
Otros consejos
Si está utilizando JPA 2.0, ahora puede usar el atributo orphanRemoval = true
de la anotación @xxxToMany
para eliminar huérfanos.
En realidad, CascadeType.DELETE_ORPHAN
ha quedado en desuso en 3.5.2-Final.
╔═════════════╦═════════════════════╦═════════════════════╗
║ Action ║ orphanRemoval=true ║ CascadeType.ALL ║
╠═════════════╬═════════════════════╬═════════════════════╣
║ delete ║ deletes parent ║ deletes parent ║
║ parent ║ and orphans ║ and orphans ║
╠═════════════╬═════════════════════╬═════════════════════╣
║ change ║ ║ ║
║ children ║ deletes orphans ║ nothing ║
║ list ║ ║ ║
╚═════════════╩═════════════════════╩═════════════════════╝
Si está utilizando JPA con EclipseLink, deberá establecer la anotación @PrivateOwned .
Documentación: Eclipse Wiki - Uso de EclipseLink JPA Extensions - Capítulo 1.4 Cómo usar la anotación @PrivateOwned
puedes usar @PrivateOwned para eliminar huérfanos por ejemplo
@OneToMany(mappedBy = "masterData", cascade = {
CascadeType.ALL })
@PrivateOwned
private List<Data> dataList;
De acuerdo con Java Persistence with Hibernate , cascade huérfano eliminar no está disponible como una anotación JPA.
Tampoco es compatible con JPA XML.
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.
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 método EntityManager.find (...)
para obtener la entidad y luego EntityManager.remove (...)
para eliminarla, los platos se eliminaron como bien.
Simplemente @OneToMany (cascade = CascadeType.ALL, mappedBy = " xxx " ;, fetch = FetchType.LAZY, orphanRemoval = true)
.
Eliminar targetEntity = MyClass.class , funciona muy bien.
Para los registros, en OpenJPA antes de JPA2 era @ElementDependant.
Estaba usando el mapeo uno a uno, pero el niño no estaba siendo eliminado.
Después de usar orphanRemoval = true, el problema se resolvió