2009-06-30 31 views
69

He estado tratando de familiarizarme con el atributo inverso de Hibernate, y parece ser solo una de esas cosas que es conceptualmente difícil.Cuándo usar inverse = false en NHibernate/Hibernate OneToMany relationships?

Lo esencial que consigo es que cuando se tiene una entidad matriz (por ejemplo, los padres) que tiene una colección de objetos secundarios utilizando un mapeo uno-a-muchos, estableciendo inversa = true en el mapeo le dice a Hibernate que " el otro lado (el Niño) tiene la responsabilidad de actualizarse para mantener la referencia de clave foránea en su tabla '.

Hacer esto parece tener 2 beneficios cuando se trata de agregar Niños a la colección en su código, y luego guardar el Padre (con conjunto de cascadas): you save an unneccessary hit on the database (porque sin conjunto inverso, Hibernate cree que tiene dos lugares para actualizar la relación FK), y de acuerdo a los documentos oficiales:

Si la columna de una asociación se declara NO NULO, NHibernate puede causar violaciónes de restricción cuando se crea o actualiza la asociación. Para evitar este problema , debe utilizar una asociación bidireccional con el muchos terminan valorada (el conjunto o bolsa) marcado como inverse = "true".

Todo parece tener sentido hasta ahora. Lo que no entiendo es esto: ¿cuándo quieres NO querer usar inversa = verdadero en una relación de uno a muchos?

Respuesta

81

Como dice Matthieu, el único caso en el que no desea establecer el inverso = verdadero es cuando no tiene sentido que el niño sea responsable de la actualización, como en el caso en que el niño no tiene conocimiento de su padre

permite tratar un mundo real, y no ejemplo en absoluto artificial:

<class name="SpyMaster" table="SpyMaster" lazy="true"> 
    <id name="Id"> 
    <generator class="identity"/> 
    </id> 
    <property name="Name"/> 
    <set name="Spies" table="Spy" cascade="save-update"> 
    <key column="SpyMasterId"/> 
    <one-to-many class="Spy"/> 
    </set> 
</class> 

<class name="Spy" table="Spy" lazy="true"> 
    <id name="Id"> 
    <generator class="identity"/> 
    </id> 
    <property name="Name"/> 
</class> 

espías pueden tener espías, sino espías nunca se sabe quién es su jefe de espías es, porque no hemos incluido los muchos-a-uno en la clase de espionaje También (convenientemente) un espía puede convertirse en delincuente y por lo tanto no necesita estar asociado con un jefe de espías. Podemos crear entidades de la siguiente manera:

var sm = new SpyMaster 
{ 
    Name = "Head of Operation Treadstone" 
}; 
sm.Spies.Add(new Spy 
{ 
    Name = "Bourne", 
    //SpyMaster = sm // Can't do this 
}); 
session.Save(sm); 

En tal caso, se debe establecer la columna de la FK ser anulable porque el acto de ahorro de SM podría insertar en la tabla maestro de espías y la tabla de Espía, y sólo después de eso ¿verdad luego actualiza la tabla de Spy para configurar el FK. En este caso, si tuviéramos que establecer inverso = verdadero, el FK nunca se actualizaría.

+0

Esto no funcionó para mí. Nunca ejecuta la actualización. Solo los inserta. – BradLaney

14

Si desea tener una asociación unidireccional, es decir, los niños no pueden navegar al elemento principal. Si es así, la columna FK debe ser NULLABLE porque los hijos se guardarán antes que el padre.

28

A pesar de la respuesta aceptada de alta votación, tengo otra respuesta a eso.

Considere un diagrama de clases con estas relaciones:

 
Parent => list of Items 
Item => Parent 

Nadie vez dicho esto, que el artículo => relación de los padres es redundante a la relación parent => Artículos. Un artículo podría hacer referencia a cualquier padre.

Pero en su aplicación, , sabe que las relaciones son redundantes. Usted sabe que las relaciones no necesitan almacenarse por separado en la base de datos. Por lo tanto, decide almacenarlo en una clave externa única, que apunta desde el elemento al elemento primario. Esta información mínima es suficiente para compilar la lista y como referencia.

Todo lo que necesita hacer para mapear esto con NH es:

  • utilizan la misma clave externa para ambas relaciones
  • tell NH que uno (la lista) es redundante a la otra y pueden ser ignorados al almacenar el objeto. (Eso es lo que NH realmente hace con inverse="true")

Estos son los pensamientos que son relevantes para el inverso. Nada más. No es una elección, solo hay una forma de mapeo correcto.


La espía Problema: Es una discusión completamente diferente si quieres apoyar una referencia del artículo a la entidad dominante. Esto depende de su modelo de negocio, NH no toma ninguna decisión al respecto. Si falta una de las relaciones, por supuesto no hay redundancia ni uso de inversa.

Mal uso: Si utiliza inverse = "true" en una lista que no tiene ninguna redundancia en la memoria, simplemente no se almacena. Si no especifica el inverso = "verdadero" si debería estar allí, NH puede almacenar la información redundante dos veces.

+0

encontré esa respuesta para ser mejor comprensible que la respuesta aceptada – r3try

+0

Mucho más simple y al punto que mi [respuesta] (http://stackoverflow.com/a/6951546/221708). –