2008-10-13 19 views
9

Tengo una entidad [Project] que contiene una colección de otras entidades [Questions].Hibernate Delete Cascade

He asignado la relación con un atributo en cascada de "all-delete-huérfano".

En mi base de datos, la relación se asigna con un campo project_id (FK) en la tabla de preguntas. este campo no puede ser nulo ya que no quiero una Pregunta sin un Proyecto.

Cuando hago session.delete (proyecto) arroja una excepción diciendo que project_id no puede ser nulo, pero si elimino la restricción no nula a ese campo, la eliminación funciona bien.

¿Alguien sabe cómo solucionar esto?

+0

Probablemente deberías mostrar las partes relevantes de tus mapeos. Uso all-delete-huérfano todo el tiempo con claves externas no nulas y nunca he tenido un problema. –

Respuesta

-2

La eliminación se está produciendo primero en el proyecto y en cascada a la pregunta, pero la eliminación del proyecto incluye una anulación del project_id en las preguntas (por integridad referencial. No se obtiene una excepción al eliminar el objeto Question , pero debido a la cascada está tratando de anular el FK en la pregunta (s).

en cuanto a "Java Persistence with Hibernate", creo que lo que realmente quiere un tipo cascada de borrar o eliminar, no elimina-huérfanos.

+0

Eso no resuelve nada –

0

Una estrategia es marcar la clave externa en la base de datos con on-delete-cascade, por lo que tan pronto como NHibernate le diga a la base de datos que elimine un proyecto, la base de datos en sí misma caerá en cascada los borrados Luego debe decirle a NHibernate que la base de datos en sí misma realiza una eliminación en cascada.

+0

¿Es posible con nhibernate 1.2? –

11

Directamente desde documentation. Esto explica su problema exactamente creo:

Sin embargo, este código

Parent p = (Parent) session.Load(typeof(Parent), pid); 
// Get one child out of the set 
IEnumerator childEnumerator = p.Children.GetEnumerator(); 
childEnumerator.MoveNext(); 
Child c = (Child) childEnumerator.Current; 

p.Children.Remove(c); 
c.Parent = null; 
session.Flush(); 

no eliminará c de la base de datos; solo eliminará el enlace a p (y provocará una violación de restricción NOT NULL, en este caso). Necesita eliminar explícitamente() al Niño.

Parent p = (Parent) session.Load(typeof(Parent), pid); 
// Get one child out of the set 
IEnumerator childEnumerator = p.Children.GetEnumerator(); 
childEnumerator.MoveNext(); 
Child c = (Child) childEnumerator.Current; 

p.Children.Remove(c); 
session.Delete(c); 
session.Flush(); 

Ahora, en nuestro caso, un Niño realmente no puede existir sin su padre. Entonces, si eliminamos un elemento secundario de la colección, realmente queremos que se elimine. Para esto, debemos usar cascade = "all-delete-huérfano".

<set name="Children" inverse="true" cascade="all-delete-orphan"> 
    <key column="parent_id"/> 
    <one-to-many class="Child"/> 
</set> 

Editar:

Con respecto a la materia inversa, creo que esto sólo determina cómo se genera el SQL, vea este doc para obtener más información.

Una cosa a tener en cuenta es, ¿tienes

not-null="true" 

en la relación uno-a-muchos en su configuración de hibernación?

+0

Lo siento. Esto funciona, pero no entiendo por qué. De los documentos dice que la verdad inversa se usa cuando mapea una asociación bidireccional (y no es mi caso), de todos modos, eso lo hace funcionar bien. Gracias.Si edita la explicación de por qué inversa = verdadero, aceptaré su respuesta –

+0

¿Hay algún ejemplo de esto en los documentos de hibernación? Me parece extraño que haya preguntado por la hibernación y haya respondido con alguna documentación nhibernata. – kbaribeau

+0

He agregado algo de información extra para ti. Me alegro de que esto haya funcionado para ti :) – abarax

Cuestiones relacionadas