【问题标题】:Grails how to map enum to existing enum on databaseGrails如何将枚举映射到数据库上的现有枚举
【发布时间】:2013-05-11 13:37:14
【问题描述】:

我有一个给定的 postgres 数据库,它使用具有以下值“M”、“F”的枚举类型。该值可以为空。当我尝试保存域对象时,我收到以下错误。

postgres 枚举:

CREATE TYPE genderlist AS ENUM ('M','F')

我的枚举:

public enum GenderCode {

    M,F

    private final String value

    private static list

    public String value() {
        return name()
    }

    public static GenderCode fromValue(String v) {
        return valueOf(v)
    }

}

域类:

class UserLog {

    String gender = null //default null
    ..
}

BootStrap.groovy:

// reading - works fine now
def rows = UserLog.list()

// insert - does not work
UserLog u = new UserLog(gender:null)
u.save()

错误:

| Batch-Entry 0 insert into user_log (active, birthyear, country, gender, user_id, id) values ('1', NULL, NULL, NULL, NULL, 98304) was cancelled.  
| ERROR: column "gender" is of type genderlist but expression is of type character varying
  Note: You will need to rewrite or cast the expression.

编辑
我更新了整个问题以匹配我项目的当前状态。由于我更新了枚举,我不再有读取数据的问题。 PGObject 被正确地转换为字符串表示。尝试插入数据时,转换仍然是一个问题。

我有一个肮脏的小变通办法:

    def sql = new Sql(dataSource_log)
    def map = [gender:'M']

    sql.executeInsert "insert into user_log (gender) values ('${map.gender}')"

我的问题仍然没有改变:我如何正确地转换字符串插入时? 'null' 值还没有被接受。 谢谢!

【问题讨论】:

    标签: grails enums grails-orm


    【解决方案1】:

    在 grails 中,您的自定义枚举存储为字符串。看看日志

    ('1', NULL, NULL, 'M', NULL, 98304)
    

    它想插入一个字符串。看起来项目中的类与数据库之间存在冲突。尝试从数据库中删除性别列表类型。
    根据我的经验,我是这样定义的:

    public enum ActivityState {
        ACTIVE("active"),
        NOT_ACTIVE("not_active")
    
        private final String value
    
        public ActivityState(String value) {
            this.value = value
        }
    
        String toString(){
            value
        }
    
        public String value() {
            value
        }
    
        public static ActivityState byValue(String value){
            values().find { it.value == value }
        }
    }
    

    这样使用:

    ActivityState activityState
    

    【讨论】:

    • 不幸的是,删除数据存储中的枚举不是一种选择。
    • 尝试添加 value() 和 byValue() 方法,可能是从字符串转换为枚举的问题。所以尽量按照说明使用。
    • @DominikH 只需删除 sqltype "genderlist"。你没有这个类型,数据库值存储为字符串。
    • 如果没有删除选项,请不要使用它。只需重命名枚举。
    【解决方案2】:

    好吧,我会说我自己修复了它,将通过直接 sql 查询保存到域类中:

    class UserLog{
    
        ...
    
        public saveIt(){
            def sql = new Sql(dataSource_log)
    
            sql.executeInsert """ 
                insert into user_log(gender,.. ) 
                values ('${this.gender}', .. ) 
                """
    
            sql.close()
        }
    }
    

    保存实例:

    Dummy d = new Dummy()
    d.gender = 'M'
    d.saveIt()
    

    无论如何,最好不要使用这种解决方法,因为查询必须随着域上的每次更改而更改。

    【讨论】:

      【解决方案3】:

      UserLog 域类中使用您的常规性别枚举,并在 UserLog 的映射中设置列的 sqlType

      class UserLog {
          GenderCode gender = null
          ...
          static mapping = {
              gender sqlType: 'enum'
          }
      }
      

      【讨论】:

      • 导致相同类型的不匹配枚举(数据库) char 变化(表达式)。但至少我可以保存具有空值的性别。我试过:UserLog u = new UserLog(gender:"M")UserLog u = new UserLog(); u.gender = GenderCode.fromValue("M") 保存前。
      猜你喜欢
      • 1970-01-01
      • 2011-05-27
      • 2011-04-14
      • 1970-01-01
      • 2019-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多