Search code examples
mysqlgrailsenumsgrails-orm

Grails 2.3.2: findOrCreate using Enums in Bootstrap


I am having troubles with using the findOrCreateBy method in the Bootstrap.groovy.

class Guest {

    String firstname
    String lastname
    Gender gender

    static constraints = {
        firstname blank: false
        lastname blank: false        
        gender nullable: false
    }
}

enum Gender {
    MALE('male'), FEMALE('female')

    final String v

    Gender(String s) { v = s }
}

And in the Bootstrap I try to create Guests if they do not exist yet.

Guest guest = Guest.findOrCreateByFirstnameAndLastnameAndGender(firstname, lastname, Gender.MALE)
guest.save()

The first time I run the app against MySQL everything works fine. The apps starts without any error. If I run the app a second time (this time with guest in the database) I get the following failure.

| Error 2013-11-17 14:27:37,621 [localhost-startStop-1] ERROR context.GrailsContextLoader  - Error initializing the application: Unknown name value [1] for enum class [ch.silviowangler.ch.cisposiamo.Gender]
Message: Unknown name value [1] for enum class [ch.silviowangler.ch.cisposiamo.Gender]
    Line | Method
->>  105 | methodMissing                    in org.grails.datastore.gorm.GormStaticApi
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    106 | createGuest                      in BootStrap
|    102 | createGuest . . . . . . . . . .  in     ''
|     66 | doCall                           in BootStrap$_closure1
|    308 | evaluateEnvironmentSpecificBlock in grails.util.Environment
|    301 | executeForEnvironment            in     ''
|    277 | executeForCurrentEnvironment . . in     ''
|    262 | run                              in java.util.concurrent.FutureTask
|   1145 | runWorker . . . . . . . . . . .  in java.util.concurrent.ThreadPoolExecutor
|    615 | run                              in     java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run . . . . . . . . . . . . . .  in java.lang.Thread

It seems the the first time Gorm writes values '0' and '1' to the database. In the second run it fails to convert these 0 and 1 into the corresponding enum value. Can anybody tell me what I am doing wrong?


Solution

  • Try this - Add the parameter generateSimpleParameterMetadata=true to your url connect string,

    ...
    url = "jdbc:mysql://localhost/bootstraptest?generateSimpleParameterMetadata=true"
    ...
    

    This has something to do with the way the driver interprets the enum meta data (frankly i don't understand it well) see http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-configuration-properties.html

    This solution is very db specific, so you don't need any other changes

    Note that the actual enum label will now be stored in the database ('NEW', 'WIP', 'DONE' instead of 0, 1, 2)