2011-06-03 12 views
7

¿Debo asignar la relación en cada dirección? Utilizando el textbook domain classes for the hasOne relationship, esto parece necesaria de mis pruebas hasta ahora para obtener los casos de reconocerse entre sí:¿Debo asignar una relación Grails hasOne en ambas direcciones?

def face = new Face() 
def nose = new Nose() 
face.nose = nose 
nose.face = face 

No sé por qué, sin embargo. Y es poco convencional incómodo. Estoy esperando que haya una mejor manera.

EDIT:

Necesito ayuda con la relación de asignación . No necesito información sobre la mecánica de establecer una relación hasOne en las clases de dominio, o una discusión sobre la sabiduría de las referencias bidireccionales. Quiero saber por qué se necesita más de una declaración única para establecer la relación entre una instancia de nariz y una instancia de cara.

Mi solución de dos declaraciones se basa en los problemas que tengo en una aplicación compleja. Voy a tratar de reproducir mi experiencia en un simple ejemplo.

+0

si aclaras qué parte es "incómoda" puedo expandir mi respuesta – hvgotcodes

+0

Es incómodo necesitar * dos * asignaciones para hacer el trabajo. Compare eso con face.addToEars (leftear), que no requiere que yo también asigne leftear.face = face. –

+0

agregó más a mi respuesta – hvgotcodes

Respuesta

17

respuesta directa

La necesidad de establecer las relaciones, es decir, para asignar la nariz para hacer frente y cara a nodo, no es realmente incómodo. Hibernate es un correlacionador RELATION, por lo que debe establecer relaciones explícitas. Dicho esto, puede escribir menos código definiendo un

setNose(nose){ 
    this.nose = nose 
    nose.face = this 
} 

en la cara. Ahora, cuando lo haga face.nose = nose, se invoca al colocador por usted y la relación se configura de la manera que desee.

pensamientos útiles Generales

En general, no es necesario asignar la relación en ambas direcciones. Es perfectamente válido tener unidireccional o relaciones bidireccionales. Sin embargo, hasOne tiene implicaciones muy específicas. La documentación establece muy claramente el propósito de hasOne es decir hibernate para poner la clave que define la relación en el niño, en este caso Nariz. Si lo piensa detenidamente, se dará cuenta de que la relación debería ser bidireccional. Aquí están los puntos de reflexión:

1) define hasOne en Face (es decir, el elemento principal).
2) aunque haya definido hasOne en el elemento primario, la tabla subyacente afectada es la tabla del elemento secundario (es decir, la columna face_id en Nariz)
3) Dado que la clave externa está en el elemento secundario, el elemento secundario debe tener referencia a su padre Si no fuera así, tendría una propiedad en el niño que es una clave externa pero no está relacionada con un objeto.
4) Recuerde, está utilizando la maquinaria de ORM para definir la relación. Si bien puede agregar manualmente un campo face_id a Nose, y configurar los valores en el código (es decir, administrar la relación usted mismo y no dejar que la herramienta ORM lo haga), el hecho de que esté utilizando ORM explícitamente significa que la herramienta ORM administrará la relación para ti.

EDITAR - ahora leyendo mi respuesta, no estaba convencido, así que escribí una prueba.Definí las clases de Rostro y Nariz como se muestra en la documentación de HasOne, pero no definí el Rostro en la Nariz. Traté de hacerlo unidireccional. Escribí una prueba para ver qué pasaba. Aquí está la prueba

class FaceTests extends GroovyTestCase { 

    public void testStuff(){ 
     Face face = new Face() 
     Nose nose = new Nose() 

     face.nose = nose; 
     face.save(flush:true) 

     assertNotNull face.id 
     assertNotNull nose.id 
    } 

} 

y el resultado es una excepción que contiene

hasOne property [Face.nose] is not bidirectional. Specify the other side of the relationship! 

Así el marco incluso se asegura, para usted, que cuando se utiliza hasOne, que tiene una relación bidireccional.

+0

Gracias por su último añadido a esta respuesta. Si agrega una segunda respuesta solo con la discusión de setNose(), la aceptaré. De esa manera, la respuesta hablará directamente a mi pregunta en su estado actual. –

+0

@jim creo que mantener una respuesta es mejor SO procedimiento. Pero he reformateado y reorganizado la respuesta al punto principal es primero y marcado como tal – hvgotcodes

Cuestiones relacionadas