5.2.1 Asociación en GORM - Reference Documentation
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith
Version: null
Table of Contents
5.2.1 Asociación en GORM
Relationships define how domain classes interact with each other. Unless specified explicitly at both ends, a relationship exists only in the direction it is defined.
Las relaciones definen cómo interactúan entre sí las clases de dominio. A menos que de forma explícita se especifique en ambos lados, una relación existe solo en la dirección que es definida.
5.2.1.1 Varios-a-uno y uno-a-uno
A many-to-one relationship is the simplest kind, and is defined with a property of the type of another domain class. Consider this example:
Una relación de varios-a-uno es el tipo más simple, se define mediante una propiedad del tipo de otra clase de dominio. Considere este ejemplo:Example A
Ejemplo A
class Face {
Nose nose
}class Nose {
}
In this case we have a unidirectional many-to-one relationship from
En este caso tenemos una relación unidireccional varios-a-uno desde Face to Nose. To make this relationship bidirectional define the other side as follows:
Face hacia Nose. Para hacer esta relación bidireccional, es necesario definir el otro lado de la siguiente manera:Example B
Ejemplo B
class Face {
Nose nose
}class Nose {
static belongsTo = [face:Face]
}
In this case we use the
En este caso establecemos mediante belongsTo setting to say that Nose "belongs to" Face. The result of this is that we can create a Face, attach a Nose instance to it and when we save or delete the Face instance, GORM will save or delete the Nose. In other words, saves and deletes will cascade from Face to the associated Nose:
belongsTo que Nose pertenece a Face. Como resultado de esto podemos crear Face, agregar una instancia de Nose y cuando guardemos o eliminemos la instancia de Face, GORM guardara o eliminara Nose. En otras palabras, la actualización y eliminación se realizaran en cascada desde Face hacia Nose.new Face(nose:new Nose()).save()
The example above will save both face and nose. Note that the inverse is not true and will result in an error due to a transient
En el ejemplo anterior ambos, face y nose serán guardados. Esto no funcionara de modo inverso y el resultado seria un error debido a un Face:
Face que es transitorio.new Nose(face:new Face()).save() // will cause an error
new Nose(face:new Face()).save() // Esto causara un error
Now if we delete the
Si borramos la instancia Face instance, the Nose will go too:
Face, Nose también sera eliminada:def f = Face.get(1) f.delete() // both Face and Nose deleted
def f = Face.get(1) f.delete() // Ambos Face y Nose serán eliminados
To make the relationship a true one-to-one, use the
Para hacer que la relación sea verdaderamente uno-a-uno, utilice la propiedad hasOne property on the owning side, e.g. Face:
hasOne en el lado que define la posesión, por ejemplo, Face:Example C
Ejemplo C
class Face {
static hasOne = [nose:Nose]
}class Nose {
Face face
}
Note that using this property puts the foreign key on the inverse table to the previous example, so in this case the foreign key column is stored in the
Tenga en cuenta que al hacer uso de esta propiedad, la clave externa sera colocada en la tabla opuesta al ejemplo anterior, por lo que en este caso la columna de clave externa se almacena en la tabla nose table inside a column called face_id. Also, hasOne only works with bidirectional relationships.
nose en una columna llamada face_id. Además, hasOne sólo funciona en las relaciones bidireccionales.
Finally, it's a good idea to add a unique constraint on one side of the one-to-one relationship:
Por último, es conveniente añadir una restricción de unicidad en un lado de la relación uno-a-uno:class Face {
static hasOne = [nose:Nose] static constraints = {
nose unique: true
}
}class Nose {
Face face
}5.2.1.2 Uno-a-varios
A one-to-many relationship is when one class, example
Una relación uno-a-varios es cuando una clase, por ejemplo Author, has many instances of a another class, example Book. With Grails you define such a relationship with the hasMany setting:
Author, tiene varias instancias de otra clase, por ejemplo Book. En Grails se establece este tipo de relación utilizando hasMany:class Author {
static hasMany = [books: Book] String name
}class Book {
String title
}
In this case we have a unidirectional one-to-many. Grails will, by default, map this kind of relationship with a join table.
En este caso tenemos una relación unidireccional uno-a-varios. De manera predeterminada, Grails mapeara este tipo de relación mediante una tabla de unión.The ORM DSL allows mapping unidirectional relationships using a foreign key association insteadEl DSL ORM permite mapear relaciones unidireccionales mediante el uso de una clave externa.
Grails will automatically inject a property of type
Grails inyectara automáticamente una propiedad de tipo java.util.Set into the domain class based on the hasMany setting. This can be used to iterate over the collection:
java.util.Set en la clase de dominio basándose en hasMany. Esta propiedad puede ser usada para iterar sobre la colección:def a = Author.get(1)for (book in a.books) {
println book.title
}The default fetch strategy used by Grails is "lazy", which means that the collection will be lazily initialized on first access. This can lead to the n+1 problem if you are not careful.De manera predeterminada Grails utilizara una estrategia de recuperación "lazy", lo que significa que la colección sera inicializada hasta que se accede por primera vez. Esto puede provocar que se incurra en el problema n+1 si usted no es cuidadoso. Si necesita recuperación "eager" puede utilizar el DSL ORM o puede especificar la recuperación "eager" como parte de una consulta
The default cascading behaviour is to cascade saves and updates, but not deletes unless a
El comportamiento predeterminado de la cascada es guardar y actualizar, pero no eliminar a menos que también se especifique belongsTo is also specified:
belongsTo:class Author {
static hasMany = [books: Book] String name
}class Book {
static belongsTo = [author: Author]
String title
}
If you have two properties of the same type on the many side of a one-to-many you have to use
Si usted tiene dos propiedades del mismo tipo en el lado varios de uno-a-varios, deberá utilizar mappedBy to specify which the collection is mapped:
mappedBy para especificar la colección a mapear:class Airport {
static hasMany = [flights: Flight]
static mappedBy = [flights: "departureAirport"]
}class Flight {
Airport departureAirport
Airport destinationAirport
}
This is also true if you have multiple collections that map to different properties on the many side:
Esto también sera válido si tiene varias colecciones que mapean a diferentes propiedades en el lado varios:class Airport {
static hasMany = [outboundFlights: Flight, inboundFlights: Flight]
static mappedBy = [outboundFlights: "departureAirport",
inboundFlights: "destinationAirport"]
}class Flight {
Airport departureAirport
Airport destinationAirport
}5.2.1.3 Varios-a-varios
Grails supports many-to-many relationships by defining a
Grails tiene soporte para relaciones varios-a-varios mediante la inclusión de hasMany on both sides of the relationship and having a belongsTo on the owned side of the relationship:
hasMany en ambos lados de la relación y del lado que expresa ser la propiedad se incluye belongsTo:class Book {
static belongsTo = Author
static hasMany = [authors:Author]
String title
}class Author {
static hasMany = [books:Book]
String name
}
Grails maps a many-to-many using a join table at the database level. The owning side of the relationship, in this case
A nivel de la base de datos Grails mapea una relación varios-a-varios mediante una tabla de unión. El lado propietario de la relación, en este caso Author, takes responsibility for persisting the relationship and is the only side that can cascade saves across.
Author, asume la responsabilidad de la persistencia de la relación y es el único que puede propagar la actualización.
For example this will work and cascade saves:
Por ejemplo, esto propagaría la creación de manera correcta:new Author(name:"Stephen King") .addToBooks(new Book(title:"The Stand")) .addToBooks(new Book(title:"The Shining")) .save()
However this will only save the
Sin embargo, esto sólo guardaría a Book and not the authors!
Book y no a los autores!new Book(name:"Groovy in Action") .addToAuthors(new Author(name:"Dierk Koenig")) .addToAuthors(new Author(name:"Guillaume Laforge")) .save()
This is the expected behaviour as, just like Hibernate, only one side of a many-to-many can take responsibility for managing the relationship.
Este es el comportamiento esperado, al igual que en Hibernate, sólo un lado de la relación varios-a-varios puede asumir la responsabilidad de la gestión.Grails' Scaffolding feature does not currently support many-to-many relationship and hence you must write the code to manage the relationship yourselfActualmente el Scaffolding de Grails no es compatible con relaciones del tipo varios-a-varios, y por lo tanto, usted deberá escribir el código para manejar este tipo de relación.
5.2.1.4 Colecciones de tipos básicos
As well as associations between different domain classes, GORM also supports mapping of basic collection types.
For example, the following class creates a
Al igual que con las asociaciones entre diferentes tipos de clases de dominio, GORM también es compatible con el mapeo de colecciones de tipos básicos. Por ejemplo, la clase siguiente, crea una asociación de nicknames association that is a Set of String instances:
nicknames que es un Set de instancias String:class Person {
static hasMany = [nicknames: String]
}
GORM will map an association like the above using a join table. You can alter various aspects of how the join table is mapped using the
GORM mapeara esta asociación utilizando una tabla de unión. Usted puede modificar varios aspectos del mapeo de la tabla de unión mediante el argumento joinTable argument:
joinTable:class Person { static hasMany = [nicknames: String] static mapping = {
hasMany joinTable: [name: 'bunch_o_nicknames',
key: 'person_id',
column: 'nickname',
type: "text"]
}
}
The example above will map to a table that looks like the following:
Al ejemplo anterior corresponderá una tabla como la siguiente:
bunch_o_nicknames Table
Tabla bunch_o_nicknames
--------------------------------------------- | person_id | nickname | --------------------------------------------- | 1 | Fred | ---------------------------------------------

