(Quick Reference)

5.2.4 Conjuntos, Listas y Mapas - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith

Version: null

5.2.4 Conjuntos, Listas y Mapas

Sets of Objects

Conjuntos de objetos

By default when you define a relationship with GORM it is a java.util.Set which is an unordered collection that cannot contain duplicates. In other words when you have:
Al definir una relación con GORM, de manera predeterminada sera un java.util.Set, una colección sin orden y que no puede contener duplicados. En otras palabras, cuando usted tiene:

class Author {
    static hasMany = [books: Book]
}

The books property that GORM injects is a java.util.Set. Sets guarantee uniquenes but not order, which may not be what you want. To have custom ordering you configure the Set as a SortedSet:
La propiedad books que GORM inyecta es un java.util.Set. El cual garantiza la unicidad de los elementos pero no el orden, lo cual puede no ser lo que usted quiere. Para personalizar el orden de los elementos establezca el conjunto como un SortedSet:

class Author {

SortedSet books

static hasMany = [books: Book] }

In this case a java.util.SortedSet implementation is used which means you must implement java.lang.Comparable in your Book class:
En este caso, se hace uso de la implementación java.util.SortedSet, esto significa que la clase Book debe implementar java.lang.Comparable:

class Book implements Comparable {

String title Date releaseDate = new Date()

int compareTo(obj) { releaseDate.compareTo(obj.releaseDate) } }

The result of the above class is that the Book instances in the books collection of the Author class will be ordered by their release date.
Como resultado de esta clase, las instancias Book en la colección books perteneciente a la clase Author, serán ordenadas por su fecha de publicación.

Lists of Objects

Listas de objetos

To keep objects in the order which they were added and to be able to reference them by index like an array you can define your collection type as a List:
Para mantener los objetos en el orden que se han añadido y poder hacer referencia a ellos por medio del índice como en un arreglo, se debe definir el tipo de colección como un List:

class Author {

List books

static hasMany = [books: Book] }

In this case when you add new elements to the books collection the order is retained in a sequential list indexed from 0 so you can do:
En este caso, cuando se añaden nuevos elementos a la colección books, el orden se mantiene en una lista secuencial, son indexados desde 0 y es posible hacer lo siguiente:

author.books[0] // get the first book
author.books[0] // obtener el primer book

The way this works at the database level is Hibernate creates a books_idx column where it saves the index of the elements in the collection to retain this order at the database level.
A nivel de la base de datos, Hibernate crea una columna books_idx donde guarda el índice de los elementos en la colección y de esta manera conserva el orden en la base de datos

When using a List, elements must be added to the collection before being saved, otherwise Hibernate will throw an exception (org.hibernate.HibernateException: null index column for collection):
Cuando se utiliza un List, los elementos se deben añadir a la colección antes de realizar el guardado, de lo contrario Hibernate arrojara una excepción (org.hibernate.HibernateException: null index column for collection):

// This won't work!
def book = new Book(title: 'The Shining')
book.save()
author.addToBooks(book)
// Esto no funcionara
def book = new Book(title: 'The Shining')
book.save()
author.addToBooks(book)

// Do it this way instead.
def book = new Book(title: 'Misery')
author.addToBooks(book)
author.save()
// Debe realizarse de esta forma.
def book = new Book(title: 'Misery')
author.addToBooks(book)
author.save()

Bags of Objects

Bags de objetos

If ordering and uniqueness aren't a concern (or if you manage these explicitly) then you can use the Hibernate Bag type to represent mapped collections.
Si el orden y la unicidad no son de importancia (o si usted realiza la gestión de manera explicita), entonces puede utilizar el tipo Bag de Hibernate para representar las colecciones mapeadas.

The only change required for this is to define the collection type as a Collection:
El único cambio requerido para esto, es definir el tipo de una colección utilizando Collection:

class Author {

Collection books

static hasMany = [books: Book] }

Since uniqueness and order aren't managed by Hibernate, adding to or removing from collections mapped as a Bag don't trigger a load of all existing instances from the database, so this approach will perform better and require less memory than using a Set or a List.
Debido a que la unicidad y el orden no son gestionados por Hibernate, añadir o eliminar elementos de una colección mapeada como Bag, no desencadenara la carga de las demás instancias desde la base de datos, por lo tanto, este método obtendrá un mejor desempeño y requiere un menor uso de memoria que cuando se usa un Set o un List.

Maps of Objects

Mapas de objetos

If you want a simple map of string/value pairs GORM can map this with the following:
Si lo que desea es un simple mapa de pares cadena-de-texto/valor, GORM puede realizar este mapeo de la siguiente manera:

class Author {
    Map books // map of ISBN:book names
}

def a = new Author() a.books = ["1590597583":"Grails Book"] a.save()

class Author {
    Map books // mapa de ISBN:título
}

def a = new Author() a.books = ["1590597583":"Grails Book"] a.save()

In this case the key and value of the map MUST be strings.
En este caso, la clave y el valor del mapa DEBEN ser cadenas de texto.

If you want a Map of objects then you can do this:
Si lo que quiere es un mapa de objetos, entonces puede hacer lo siguiente:

class Book {

Map authors

static hasMany = [authors: Author] }

def a = new Author(name:"Stephen King")

def book = new Book() book.authors = [stephen:a] book.save()

The static hasMany property defines the type of the elements within the Map. The keys for the map must be strings.
La propiedad estática hasMany define el tipo de elementos que contendrá el mapa. Las claves del mapa deben ser cadenas de texto.

A Note on Collection Types and Performance

Acerca de los tipos de colecciones y el desempeño

The Java Set type doesn't allow duplicates. To ensure uniqueness when adding an entry to a Set association Hibernate has to load the entire associations from the database. If you have a large numbers of entries in the association this can be costly in terms of performance.
El tipo Set de Java no permite duplicados. Para garantizar la unicidad cuando se añade una entrada en una asociación Set, Hibernate debe cargar la asociación completa de la base de datos. Si la asociación contiene una gran cantidad de elementos, esto podría resultar costoso en términos de rendimiento.

The same behavior is required for List types, since Hibernate needs to load the entire association to maintain order. Therefore it is recommended that if you anticipate a large numbers of records in the association that you make the association bidirectional so that the link can be created on the inverse side. For example consider the following code:
El mismo funcionamiento aplica para el tipo List debido a que para mantener el orden de los elementos, Hibernate necesita cargar la asociación entera. Por lo tanto, si espera una gran cantidad de registros en la asociación, es recomendable definirla de manera bidireccional, así el enlace puede ser creado en el lado contrario:

def book = new Book(title:"New Grails Book")
def author = Author.get(1)
book.author = author
book.save()

In this example the association link is being created by the child (Book) and hence it is not necessary to manipulate the collection directly resulting in fewer queries and more efficient code. Given an Author with a large number of associated Book instances if you were to write code like the following you would see an impact on performance:
En este ejemplo, se crea la asociación por el elemento hijo (Book) y por lo tanto, no es necesario operar directamente sobre la colección, el resultado es un menor numero de consultas y el código es más eficiente. Teniendo en cuenta un Author con una gran cantidad de instancias Book asociadas, si tuviera que escribir código como el siguiente notaria el resultado en el rendimiento:

def book = new Book(title:"New Grails Book")
def author = Author.get(1)
author.addToBooks(book)
author.save()

You could also model the collection as a Hibernate Bag as described above.
También podría modelar la colección utilizando un Bag de Hibernate como se describió anteriormente.