2010-09-20 12 views
15

en Grails, ¿Hay alguna forma de limitar el tamaño de la columna a la que se asigna la enumeración? En el siguiente ejemplo, me gustaría el tipo de columna para ser Char (2)Grails Enum Mapeo

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

class Foo { 
    FooStatus status 

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

tanto INLIST y el tamaño no tiene ningún efecto cuando se exporta el esquema, el tipo de columna mantiene su valor por defecto (varch (255)) Tal vez podría hacer eso si defino un nuevo UserType. Alguna idea ?

Gracias -ken

Respuesta

20

no creo que es directamente posible dada la forma en enumeraciones se asignan internamente en GORM. Pero cambiar el código para que esto funcione:

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 } 
    } 
} 

y

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)' 
    } 
} 

Agregar el captador transitoria y colocador le permite establecer u obtener ya sea la cadena (id) o valor de enumeración.

+0

Es bastante molesto que tenga que agregar para cada enumeración un tipo getter y setter y también lo declaro como "transitorio". Burt, ¿no sería un UserType personalizado una solución más elegante? – ken

+0

Transient y getter/setter son opcionales si está bien con la configuración de la identificación de Enum y la conversión de la id a la instancia enum en el código de llamada. El cambio real es persistir en una Cadena en lugar de Enum (lo cual fue implícito por el uso de inList() ya que de todos modos eso no funcionaría con la Enum). Pero claro, un UserType personalizado debería funcionar. Querrá extraer cosas comunes en una clase base si lo hace más de una vez. Mi preferencia sería mantener todo en la clase de dominio si es posible, siempre y cuando los cambios no sean tan significativos. –

+0

Burt, sí, tienes razón, quiero poder establecer y obtener la variable de estado como una enumeración y también poder guardar la base de datos, así el uso de la identificación en la enumeración. Me estoy inclinando más hacia un tipo de usuario personalizado algo a lo largo de mapping = {status type: EnumUserType} – ken

11

Grails se envía con un mapeo Hibernate personalizado no documentado (por lo que puedo decir de todos modos) para enums. La clase es org.codehaus.groovy.grails.orm.hibernate.cfg.IdentityEnumType. No le permitirá establecer el tamaño de la columna, pero sí facilita el cambio de lo que está almacenado en el DB para cada valor enum sin tener que agregar campos transitorios a su modelo.

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 } 
    } 
} 

Puede ejecutar un 'alter table' en Bootstrap.groovy para reducir el tamaño de la columna:

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

de qué versión estás hablando? – genuinefafa

+0

¿Estás preguntando sobre la versión de Grails? 2.2.1 y otros –

+0

¡Tuve que declarar mi enumeración en otro archivo para poder trabajar! – lfrodrigues

2

Incluso más fácil (funciona al menos en 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

Dado que GORM 6.1 identity enum mapping se puede habilitar con Tal construcción

static mapping = { 
    myEnum enumType:"identity" 
}