Search code examples
grailsgroovygrails-orm

Grails : Adding data in a many-to-many relationship generate an error


I've created a many-to-many relationship between two object in Grails 2.4 but when I try to add data in my bootstrap file, it fails and give me this error

Message: No signature of method: ca.ogsl.romm.observation.Behavior.addToTaxonGroup() is applicable for argument types: (ca.ogsl.romm.observation.TaxonGroup) values: [ca.ogsl.romm.observation.TaxonGroup : (unsaved)]
Possible solutions: addToTaxonGroups(java.lang.Object)

These are my domain class

Behavior.groovy

class Behavior {
    int id
    String code
    String nameFr
    String nameEn

    static belongsTo = TaxonGroup
    static hasMany = [taxonGroups: TaxonGroup]

    static constraints = {
        nameFr nullable: true
        nameEn nullable: true
    }
}

TaxonGroup.groovy

class TaxonGroup {
    int id
    String code
    String nameFr
    String nameEn

    static hasMany = [behaviors: Behavior]

    static constraints = {
        nameFr nullable: true
        nameEn nullable: true
        behaviors nullable: true
    }
}

Finaly, this is the code in my BootStrap.groovy

new Behavior(code: "basking")
            .addToTaxonGroup(new TaxonGroup(code:"reptiles"))
            .save()

I've been searching for hours and try many adding ways but nothing seems to solve this issue...

Anyone as an idea of what I'm doing wrong? Thank you very much for your time!!!


Solution

  • The addToXXX and removeFromXXX dynamic methods are created from the key in the hasMany map; this is also the name of the Set or List that Grails adds to the class for you to hold the items. Prefix with addTo (or removeFrom) and capitalize the first letter - so for taxonGroups it would be addToTaxonGroups, not addToTaxonGroup. Likewise for behaviors it'd be addToBehaviors and removeFromBehaviors.

    Also, unrelated (and not a problem) - remove behaviors nullable: true; that doesn't have any effect. Collections (except when you first instantiate the class instance) are either empty or have one or more items, but will never be null in a persistence instance.

    And delete int id - Grails adds a Long id property to the bytecode for you during compilation via an AST, and there's rarely any benefit of redundantly specifying the property since pretty much every editor/IDE/etc. expects there to be an id field, so it won't help with autocomplete, etc.