Grails

Add persistence support to Collections and Maps of basic (no domain classes) types

Details

  • Type: Sub-task Sub-task
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Fixed
  • Affects Version/s: 0.5-RC1
  • Fix Version/s: 1.1-beta1
  • Component/s: Persistence
  • Labels:
    None

Description

I have to put a simple list of names as a domain class attribute, but a list of strings doesnt work, and I have to do a domain class to wrap strings in it to make it works. It'll fine if I cand do things like:

class XXXX {
List names = []
}

and the names on the list persists to the db without more work.

What I've tried to do is something like this:
class Pepe {
List names
static hasMany = [names: String]
}

thanks.

Activity

Hide
Alex Wei added a comment -

First of all, it must be decided on how to store the collection of basic types in a relational database.

Option 1:
Use JDBC ARRAY type.

Option 2:
Use Java serialization to store the whole collection in a column of byte array. (BLOB or VARBINARY or LONGVARBINARY).

Option 3:
Use XML serialization to store the whole collection in a column of VARCHAR or LONGVARCHAR.

Option 4:
Store the collection in a separate table.

Option 5:
Hacks, such as comma-delimited String... What about having a comma in a String element? What about various types within one array?

As there are workarounds, I propose to lower the priority to 'Minor'.

Show
Alex Wei added a comment - First of all, it must be decided on how to store the collection of basic types in a relational database. Option 1: Use JDBC ARRAY type. Option 2: Use Java serialization to store the whole collection in a column of byte array. (BLOB or VARBINARY or LONGVARBINARY). Option 3: Use XML serialization to store the whole collection in a column of VARCHAR or LONGVARCHAR. Option 4: Store the collection in a separate table. Option 5: Hacks, such as comma-delimited String... What about having a comma in a String element? What about various types within one array? As there are workarounds, I propose to lower the priority to 'Minor'.
Hide
Pablo Pazos Gutierrez added a comment -

Hi, option 5 breaks database 1st normal form.

I think separating the tables is a good option. Maybe it's a good idea to set the table name to something that denotes that is a table of datavalues and not a mapping from a domain class, something like: string_collection_1234 or string_map_3214, and the mapping table of the domain class that has this attribute (collection or map of strings) reference to those table names, I'm only thinking about it, I dont know very much about how hibernate works.

Show
Pablo Pazos Gutierrez added a comment - Hi, option 5 breaks database 1st normal form. I think separating the tables is a good option. Maybe it's a good idea to set the table name to something that denotes that is a table of datavalues and not a mapping from a domain class, something like: string_collection_1234 or string_map_3214, and the mapping table of the domain class that has this attribute (collection or map of strings) reference to those table names, I'm only thinking about it, I dont know very much about how hibernate works.
Hide
Peter Ledbrook added a comment -

Looks like Hibernate supports collections of basic types by creating a dedicated table. The mapping looks like this:

<set name="names" table="person_names">
    <key column="person_id"/>
    <element column="person_name" type="string"/>
</set>

More info here:

http://www.hibernate.org/hib_docs/v3/reference/en/html/collections.html#collections-ofvalues

Show
Peter Ledbrook added a comment - Looks like Hibernate supports collections of basic types by creating a dedicated table. The mapping looks like this:
<set name="names" table="person_names">
    <key column="person_id"/>
    <element column="person_name" type="string"/>
</set>
More info here: http://www.hibernate.org/hib_docs/v3/reference/en/html/collections.html#collections-ofvalues
Hide
Pam added a comment -

Hi, I am also trying to do this, like this:

class NetworkOperator{
String name
HashMap otherNames = new HashMap()

static hasMany = [otherNames:String]
}

I would expect this to work in a dedicated table, I will probably use Peter's Hibernate manual mapping for now. It would be very nice if grails could do this on it's own... Thanks!

Show
Pam added a comment - Hi, I am also trying to do this, like this: class NetworkOperator{ String name HashMap otherNames = new HashMap() static hasMany = [otherNames:String] } I would expect this to work in a dedicated table, I will probably use Peter's Hibernate manual mapping for now. It would be very nice if grails could do this on it's own... Thanks!
Hide
Graeme Rocher added a comment - - edited

GORM now supports basic collection types using a join table:

class Person {
    static hasMany = [nicknames:String]
}

Grails will map a new join table called "person_nicknames":

person_id string
1 "joejoe"
1 "yoyo"

You can change the mapping using the joinTable argument:

class Person {
    static hasMany = [nicknames:String]

    static mapping = {
       hasMany joinTable:[name:'bunch_o_nicknames', key:'person_id', column:'nickname', type:"text"]       
    } 
}
Show
Graeme Rocher added a comment - - edited GORM now supports basic collection types using a join table:
class Person {
    static hasMany = [nicknames:String]
}
Grails will map a new join table called "person_nicknames":
person_id string
1 "joejoe"
1 "yoyo"
You can change the mapping using the joinTable argument:
class Person {
    static hasMany = [nicknames:String]

    static mapping = {
       hasMany joinTable:[name:'bunch_o_nicknames', key:'person_id', column:'nickname', type:"text"]       
    } 
}
Hide
Graeme Rocher added a comment -

minor edit made to description of fix

Show
Graeme Rocher added a comment - minor edit made to description of fix

People

Vote (4)
Watch (3)

Dates

  • Created:
    Updated:
    Resolved: