2009-11-11 13 views
18

Tengo dos clases A y B. Muchas B pueden tener asociación con una sola A, por lo tanto, una relación de varios a uno desde B hasta A . me ha trazado la relación como:cómo definir una eliminación de cascada inversa en una asignación de muchos a uno en hibernación

<class name="A" table="tbl_A"> 
    <property name="propA" column="colA"/> 
</class> 
<class name="B" table="tbl_B"> 
    <property name="propB" column="colB"/> 
    <many-to-one name="a" class="A" column="col1" cascade="delete"/> 
</class> 

a tiene nada asignada a B. Teniendo esto en cuenta tenemos la intención de eliminar B cuando se asocia se elimina una. Esto podría haber sido posible si pudiera definir un inverso = "verdadero" en la asociación muchos a uno en B, pero Hibernate no lo permite.

¿Alguien puede ayudar con esto? No queremos escribir nada en A para esto.

+0

Lo probé yo mismo, no creo que sea posible. Puede ser un error en hibernación, o hibernar puede pensar que hay una relación de uno a muchos en el otro lado, y decidir que eliminar un miembro de una colección, no debería resultar en la eliminación del objeto principal, así como en todas las objetos en esa colección también. – Zoidberg

+0

¿Puedes confirmar que lo que quieres hacer es eliminar A y todas las B asociadas a A? –

+0

@Pascal sí, esa es mi intención –

Respuesta

24

Hibernate solo conecta en cascada a lo largo de las asociaciones definidas. Si A no sabe nada de Bs, nada de lo que hagas con A afectará a Bs.

sugerencia de Pascal es, por lo tanto, la manera más fácil de hacer lo que quiere:

<class name="A" table="tbl_A"> 
    ... 
    <set name="myBs" inverse="true" cascade="all,delete-orphan"> 
    <key column="col1"/> 
    <one-to-many class="B"/> 
    </set> 
</class> 

<class name="B" table="tbl_B"> 
    ... 
    <many-to-one name="a" class="A" column="col1" not-null="true"/> 
</class> 

Tenga en cuenta que el establecimiento cascade="delete" en B a medida que lo tiene en su código original no va a hacer lo que quiere - que le dice a Hibernate para "eliminar A si B se elimina", lo que probablemente resultará en una violación de la restricción (si hay otras B vinculadas a esa A).

Si no puede agregar una colección de Bs a A (aunque no puedo pensar en las circunstancias en las que sería el caso), su única otra alternativa es definir la eliminación en cascada de A a B en el nivel de clave extranjera; sus Bs se eliminarán cuando su A sea eliminada.

Esta es una solución bastante feo, sin embargo, ya que hay que tener mucho cuidado de cómo se elimina una de Hibernate:

  1. Sesión debe lavarse antes de borrar un actualizaciones (que tiene pendientes a B puede resultar en un error o A y algunas BS se vuelven a insertar detrás de las escenas)
  2. Todos los Bs vinculados a su A (y ya que no mantiene la relación del lado A que significa todos Bs) deben ser desalojados de todos sesiones activas y segundo nivel de caché.
+2

Bueno, +1 también para esta respuesta completa y clara. Realmente necesito mejorar la forma en que explico cosas sobre Hibernate en inglés :) –

+1

@Pascal - gracias. Creo que tu inglés está perfectamente bien, por cierto. Por otra parte, tampoco es mi primer idioma, entonces, ¿qué sé? :-) – ChssPly76

+0

No quiero mapear colecciones pero Hibernate me obliga a hacerlo ya que es necesario realizar una cascada. Creado un problema: https://hibernate.atlassian.net/browse/HHH-8403 – djmj

7

Creo que necesita cascade="all,delete-orphan" de A a B con una asociación one-to-many.

+0

+1. No es lo que OP está pidiendo, pero es la (única) forma correcta de hacerlo. – ChssPly76

Cuestiones relacionadas