【问题标题】:Grails Enum MappingGrails 枚举映射
【发布时间】:2011-04-14 12:11:24
【问题描述】:

在 Grails 中,有没有办法限制枚举映射到的列的大小。在以下示例中,我希望列类型为 char(2)

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

class Foo {
    FooStatus status

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

inList和size在导出schema时都没有任何作用,列类型保持默认值(varch(255)) 如果我定义一个新的用户类型,也许我可以这样做。有什么想法吗?

谢谢 -ken

【问题讨论】:

    标签: grails grails-orm


    【解决方案1】:

    鉴于枚举在 GORM 内部映射的方式,我认为这不是直接可能的。但是将代码更改为此有效:

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

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

    添加瞬态 getter 和 setter 允许您设置或获取字符串 (id) 或枚举值。

    【讨论】:

    • 我必须为每个枚举类型添加一个 getter 和一个 setter 并将其声明为“瞬态”,这很烦人。 Burt,自定义 UserType 不是更优雅的解决方案吗?
    • transient 和 getter/setter 是可选的,如果您可以设置 Enum 的 id 并将 id 转换为调用代码中的枚举实例。真正的变化是保留一个 String 而不是 Enum (这是您使用 inList() 所暗示的,因为无论如何这对 Enum 都不起作用)。但可以肯定的是,自定义 UserType 应该可以工作。如果您不止一次这样做,您会希望将常见的东西提取到基类中。我的偏好是尽可能将所有内容保留在域类中,只要更改不是那么重要。
    • Burt,是的,你是对的,我希望能够将状态变量设置和获取为枚举,并且还能够保存数据库,从而在枚举中使用 id。我更倾向于沿着 mapping= {status type:EnumUserType } 自定义用户类型
    • Burt,你知道 JIRA 中是否有这个问题吗?您应该能够在映射块中为 Enum 提供 sqlType。
    【解决方案2】:

    Grails 附带了一个未记录的(据我所知)用于枚举的自定义 Hibernate 映射。该类是 org.codehaus.groovy.grails.orm.hibernate.cfg.IdentityEnumType。它不会让您设置列大小,但可以轻松更改每个枚举值在数据库中存储的内容,而无需向模型添加瞬态字段。

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

    您可以在 Bootstrap.groovy 中运行“更改表”来缩小列:

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

    【讨论】:

    • 你说的是哪个版本?
    • 您问的是 Grails 版本吗? 2.2.1及其他
    【解决方案3】:

    更简单(至少在 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
        }
    }
    

    【讨论】:

      【解决方案4】:

      由于 GORM 6.1 身份枚举映射可以使用这种构造启用

      static mapping = {
         myEnum enumType:"identity"
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-27
        • 1970-01-01
        • 1970-01-01
        • 2017-03-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多