Grails
  1. Grails
  2. GRAILS-3396 Top level task: GORM Improvements
  3. GRAILS-1023

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

    Details

    • Type: Sub-task Sub-task
    • Status: 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

          • Assignee:
            Graeme Rocher
            Reporter:
            Pablo Pazos Gutierrez
          • Votes:
            4 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development