2010-09-20 12 views
15

w Grails, Czy istnieje sposób na ograniczenie rozmiaru kolumny, na której mapowane jest wyliczenie. W poniższym przykładzie chciałbym typ kolumny, aby być char (2)Graum Enum Mapowanie

enum FooStatus { 
    BAR('br'), TAR('tr') 
    final static String id 
} 

class Foo { 
    FooStatus status 

    static constraints = { 
     status(inList:FooStatus.values()*.id,size:2..2) 
    } 
} 

zarówno inList i rozmiar nie mają żadnego wpływu podczas eksportowania schematu, typ kolumna zachowuje swoją wartość domyślną (varch (255)) Może mógłbym to zrobić, jeśli zdefiniuję nowy UserType. Dowolny pomysł ?

Dziękuję -ken

Odpowiedz

20

Nie sądzę, że to możliwe, biorąc pod uwagę bezpośredni sposób teksty stałe odwzorowywane są wewnętrznie w GORM. Ale zmiany kodu tego działa:

enum FooStatus { 
    BAR('br'), 
    TAR('tr') 
    private FooStatus(String id) { this.id = id } 
    final String id 

    static FooStatus byId(String id) { 
     values().find { it.id == id } 
    } 
} 

i

class Foo { 
    String status 

    FooStatus getFooStatus() { status ? FooStatus.byId(status) : null } 
    void setFooStatus(FooStatus fooStatus) { status = fooStatus.id } 

    static transients = ['fooStatus'] 

    static constraints = { 
     status inList: FooStatus.values()*.id 
    } 

    static mapping = { 
     status sqlType: 'char(2)' 
    } 
} 

dodanie przemijające getter i setter pozwala ustawić lub dostać albo String (ID) lub wartość enum.

+0

To dość denerwujące, że muszę dodać dla każdego wyliczenia typu getter i seter, a także zadeklarować go jako "przejściowy". Burt, czy niestandardowy UserType nie byłby bardziej eleganckim rozwiązaniem? – ken

+0

Transient i getter/setter są opcjonalne, jeśli dobrze jest ustawić identyfikator Enum i przekonwertować identyfikator na instancję wyliczającą w kodzie wywołującym. Prawdziwą zmianą jest zachowanie łańcucha zamiast Enum (co było w pewien sposób sugerowane przez użycie inList(), ponieważ i tak nie działałoby to z Enum). Ale na pewno powinien działać niestandardowy UserType. Chcesz wydobyć typowe elementy do klasy bazowej, jeśli robisz to więcej niż raz. Wolałbym zachować wszystko w klasie domeny, o ile to możliwe, o ile zmiany nie są tak znaczące. –

+0

Burt, tak masz rację, chcę móc ustawić i uzyskać zmienną statusu jako element wyliczający, a także być w stanie zapisać bazę danych, wykorzystując w ten sposób identyfikator w wyliczeniu. Przechodzę bardziej w kierunku niestandardowego typu użytkownika coś wzdłuż odwzorowania = {typ statusu: EnumUserType} – ken

11

Grails są dostarczane z nieudokumentowanym (o ile mogę powiedzieć) niestandardowym mapowaniem Hibernate do wyliczeń. Klasa to org.codehaus.groovy.grails.orm.hibernate.cfg.IdentityEnumType. Nie pozwoli ci ustawić rozmiaru kolumny, ale ułatwia zmianę tego, co jest przechowywane w DB dla każdej wartości wyliczeniowej bez konieczności dodawania zmiennych przejściowych do twojego modelu.

import org.codehaus.groovy.grails.orm.hibernate.cfg.IdentityEnumType 

class MyDomainClass { 
    Status status 

    static mapping = { 
     status(type: IdentityEnumType) 
    } 

    enum Status { 
     FOO("F"), BAR("B") 
     String id 
     Status(String id) { this.id = id } 
    } 
} 

można uruchomić 'alter table' w Bootstrap.groovy się kurczyć kolumnę:

DataSource dataSource 
... 
Sql sql = new Sql(dataSource) 
sql.execute("alter table my_domain_class change column status status varchar(1) not null") 
+0

o której wersji mówisz? – genuinefafa

+0

Pytasz o wersję Grails? 2.2.1 i inne –

+0

Musiałem zadeklarować moje wyliczenie w innym pliku, aby pracować! – lfrodrigues

2

Nawet łatwiej (działa przynajmniej w Grails 2.1.0+)

class DomainClass { 
    Status status 
    static mapping = { 
     status(enumType: "string") 
    } 
} 

enum Status { 
    OPEN  ("OPEN"), 
    CLOSED ("CLOSED"), 
    ... 

    String name 
    Status (String name) { 
     this.name = name 
    } 
} 
1

Od mapowania wyliczenia tożsamości GORM 6.1 można włączyć za pomocą taki konstrukt:

static mapping = { 
    myEnum enumType:"identity" 
}