Persistierung von Enums in Grails

Das mit Java 5 eingeführte Aufzählungsobjekt Enum ist in vielerlei Fällen äußerst hilfreich. Der komfortable Einsatz dieses Datentypen in Grails gestaltet sich mitunter allerdings etwas trickreich.

Zur Verdeutlichung des Problems greifen wir auf eine Person zurück, dessen Fähigkeiten wir abbilden wollen. In unserem Falle handelt es sich dabei um ein festen Satz an Fähigkeiten, der unveränderlich ist und den wir daher wir als Skill in Form eines Aufzählungsobjektes darstellen möchten. Die Person und ihre Fähigkeiten werden anschließend über eine 1:n Beziehung miteinander verknüpft.

Mein ursprünglicher Gedanke sieht daher folgendermaßen aus:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Person {
    String name
    static hasMany = [skills: Skill]
    static constraints = {
        name blank: false
    }
}

enum Skill {
    CODING,
    GAMING,
    SKIING;
}

Beim Versuch diese Beziehung zu persistieren rennen wir allerdings in eine java.lang.ClassCastException mit der Meldung java.lang.String cannot be cast to java.lang.Enum hinein. Anscheinend versucht GORM an dieser Stelle unser Aufzählungsobjekt in eine Zeichenkette zu pressen, was jedoch kläglich scheitert.

Mit Version 1.1 Beta 2 von Grails wurde die erweiterte Unterstützung von Enum integriert. Dabei bezieht GORM nun den zu persistierenden Wert über die Methode getId() von dem Enum. Daher wandeln wir unseren Code wie folgt ab:

1
2
3
4
5
6
7
8
9
enum Skill {
    CODING('C'),
    GAMING('G'),
    SKIING('S');

    final String id

    Skill(String id) { this.id = id }
}

Bei der Persistierung stoßen wir nun nicht mehr auf eine java.lang.ClassCastException, allerdings auch nicht auf die Lösung des Problems, da unsere Werte als NULL in der Datenbank untergebracht werden.

Nach einiger Tüftelei bin ich auf folgenden Workaround gestoßen, wobei wir die Elemente von skills als String definieren:

1
2
3
4
5
6
7
class Person {
    String name
    static hasMany = [skills: String]
    static constraints = {
        name blank: false
    }
}

Es läuft zwar, allerdings hätte ich mir gewünscht das GORM selbstständig in der Lage gewesen wäre den Datentyp von getId() zu ermitteln und entsprechend zu berücksichtigen.