Estoy un poco confundido sobre el orphanRemovalatributo JPA 2.0 .
Creo que puedo ver que es necesario cuando uso las herramientas de generación de DB de mi proveedor de JPA para crear la base de datos subyacente DDL para tener una ON DELETE CASCADErelación particular.
Sin embargo, si el DB existe y ya tiene una ON DELETE CASCADErelación, ¿no es esto suficiente para poner en cascada la eliminación de manera adecuada? ¿Qué hace el orphanRemovalademás?
Salud
fuente

Un ejemplo tomado aquí :
Cuando
Employeese elimina un objeto de entidad, la operación de eliminación se conecta en cascada alAddressobjeto de entidad al que se hace referencia . En este sentido,orphanRemoval=trueycascade=CascadeType.REMOVEson idénticos, y siorphanRemoval=truese especifica,CascadeType.REMOVEes redundante.La diferencia entre las dos configuraciones está en la respuesta a la desconexión de una relación. Por ejemplo, como cuando se configura el campo de dirección
nulla otroAddressobjeto.Si
orphanRemoval=truese especifica, laAddressinstancia desconectada se elimina automáticamente. Esto es útil para limpiar objetos dependientes (por ejemploAddress) que no deberían existir sin una referencia de un objeto propietario (por ejemploEmployee).Si solo
cascade=CascadeType.REMOVEse especifica, no se realiza ninguna acción automática ya que desconectar una relación no es una operación de eliminación.Para evitar referencias colgantes como resultado de la eliminación de huérfanos, esta función solo debe habilitarse para los campos que contienen objetos dependientes privados no compartidos.
Espero que esto lo aclare más.
fuente
En el momento en que elimine una entidad secundaria de la colección, también eliminará esa entidad secundaria de la base de datos. orphanRemoval también implica que no puede cambiar de padres; Si hay un departamento que tiene empleados, una vez que elimine a ese empleado para colocarlo en otro departamento, habrá eliminado sin darse cuenta a ese empleado de la base de datos en flush / commit (lo que ocurra primero). La moral es establecer huérfanoRemoval en verdadero siempre que esté seguro de que los hijos de ese padre no migrarán a un padre diferente a lo largo de su existencia. Al activar huérfano, Removal también agrega automáticamente REMOVE a la lista en cascada.
fuente
department.remove(emp);ese empleado se elimina de la tabla emp sin ni siquiera llamarcommit()El mapeo JPA equivalente para el DDL
ON DELETE CASCADEescascade=CascadeType.REMOVE. La eliminación huérfana significa que las entidades dependientes se eliminan cuando se destruye la relación con su entidad "principal". Por ejemplo, si un hijo se elimina de una@OneToManyrelación sin eliminarlo explícitamente en el administrador de la entidad.fuente
cascade=CascadeType.REMOVENO es equivalente aON DELETE CASCADE. Al eliminar en el código de la aplicación y no afecta a DDL, otro ejecutado en DB. Ver stackoverflow.com/a/19696859/548473La diferencia es:
- orphanRemoval = true: la entidad "Secundaria" se elimina cuando ya no se hace referencia a ella (su padre no se puede eliminar).
- CascadeType.REMOVE: la entidad "Secundaria" se elimina solo cuando se elimina su "Principal".
fuente
Transiciones de estado de entidad
JPA traduce las transiciones de estado de la entidad a sentencias SQL, como INSERT, UPDATE o DELETE.
Cuando usted es
persistuna entidad, está programando la instrucción INSERT para que se ejecute cuandoEntityManagerse vacía, de forma automática o manual.cuando eres
removeuna entidad, estás programando la declaración DELETE, que se ejecutará cuando se vacíe el Contexto de persistencia.Transiciones de estado de entidad en cascada
Por conveniencia, JPA le permite propagar las transiciones de estado de la entidad de las entidades principales a las secundarias.
Entonces, si tiene una
Postentidad principal que tiene una@OneToManyasociación con laPostCommententidad secundaria:La
commentscolección en laPostentidad se asigna de la siguiente manera:CascadeType.ALL
El
cascadeatributo le dice al proveedor de JPA que pase la transición del estado de laPostentidad de la entidad principal a todas lasPostCommententidades contenidas en elcommentscolección.Entonces, si elimina la
Postentidad:El proveedor de JPA eliminará
PostCommentprimero la entidad, y cuando se eliminen todas las entidades secundarias, también eliminará laPostentidad:Retiro de huérfanos
Cuando establezca el
orphanRemovalatributo entrue, el proveedor de JPA programará unaremoveoperación cuando la entidad secundaria se elimine de la colección.Entonces, en nuestro caso,
El proveedor de JPA eliminará el
post_commentregistro asociado ya que laPostCommententidad ya no está referenciada en lacommentscolección:EN ELIMINAR CASCADA
El
ON DELETE CASCADEse define en el nivel FK:Una vez que haga eso, si elimina una
postfila:El
post_commentmotor de la base de datos elimina automáticamente todas las entidades asociadas . Sin embargo, esta puede ser una operación muy peligrosa si elimina una entidad raíz por error.Conclusión
La ventaja de JPA
cascadey lasorphanRemovalopciones es que también puede beneficiarse del bloqueo optimista para evitar actualizaciones perdidas .Si usa el mecanismo de cascada JPA, no necesita usar el nivel DDL
ON DELETE CASCADE, que puede ser una operación muy peligrosa si elimina una entidad raíz que tiene muchas entidades secundarias en varios niveles.Para obtener más detalles sobre este tema, consulte este artículo .
fuente
CascadeType. Es un mecanismo complementario. Ahora, está confundiendo la eliminación con la persistencia. La eliminación de huérfanos se trata de eliminar asociaciones sin referencia, mientras que la persistencia se trata de salvar nuevas entidades. Debe seguir los enlaces proporcionados en la respuesta para comprender mejor estos conceptos.@GaryK respuesta es absolutamente genial, he pasado una hora buscando una explicación
orphanRemoval = truefrenteCascadeType.REMOVEy me ayudó a entender.En resumen:
orphanRemoval = truefunciona de la misma manera queCascadeType.REMOVESÓLO SI eliminamos object (entityManager.delete(object)) y queremos que también se eliminen los objetos del niño.En una situación completamente diferente, cuando busquemos algunos datos como
List<Child> childs = object.getChilds()y luego eliminemos un child (entityManager.remove(childs.get(0)) usandoorphanRemoval=true, la entidad correspondientechilds.get(0)se eliminará de la base de datos.fuente
la eliminación huérfana tiene el mismo efecto que EN ELIMINAR CASCADA en el siguiente escenario: - Digamos que tenemos una relación simple de uno a uno entre la entidad estudiantil y una entidad guía, donde muchos estudiantes pueden asignarse a la misma guía y en la base de datos tenemos un relación de clave externa entre el alumno y la tabla de guía de modo que la tabla del alumno tenga id_guide como FK.
// La entidad principal
En este escenario, la relación es tal que la entidad estudiantil es la propietaria de la relación y, como tal, necesitamos guardar la entidad estudiantil para poder conservar todo el gráfico del objeto, por ejemplo
Aquí estamos mapeando la misma guía con dos objetos de estudiantes diferentes y dado que se utiliza CASCADE.PERSIST, el gráfico de objetos se guardará como se muestra a continuación en la tabla de la base de datos (MySql en mi caso)
Mesa ESTUDIANTE: -
ID Nombre Dept Id_Guide
1 Roy ECE 1
2 Nick ECE 1
Tabla de GUÍA: -
ID NOMBRE Salario
1 Juan $ 1500
y ahora si quiero eliminar a uno de los estudiantes, usando
y cuando se elimina un registro de estudiante, el registro de guía correspondiente también debe eliminarse, ahí es donde entra en escena el atributo CASCADE.REMOVE en la entidad de Estudiante y lo que hace es; elimina al estudiante con el identificador 1 y el objeto de guía correspondiente (identificador 1) Pero en este ejemplo, hay un objeto de estudiante más que se asigna al mismo registro de guía y, a menos que usemos el atributo orphanRemoval = true en la entidad de guía, el código de eliminación anterior no funcionará.
fuente