【问题标题】:Grails 2.5:domainObj.validate() method returns false when domainObj.properties=paramsGrails 2.5:domainObj.validate() 方法在 domainObj.properties=params 时返回 false
【发布时间】:2017-01-19 17:28:43
【问题描述】:

我正在尝试将我的 grails 应用程序从 1.3 版升级到 2.5 版。我有一个域类,其中一个字段是枚举。在控制器中,当我执行 domainObj.validate() 时,它总是返回 false。验证错误是 -

grails.validation.ValidationErrors: 1 个错误 字段“typeEnum”上的对象“参数”中的字段错误:拒绝值 [0];代码 [com.TypeEnum.typeMismatch.error,com.TypeEnum.typeMismatch,com.TypeEnum.typeMismatch.error,com.TypeEnum.typeMismatch,typeMismatch.com.TypeEnum,typeMismatch.pspValueTypeEnum,typeMismatch.com.TypeEnum,typeMismatch];参数 [typeEnum];默认消息[No enum constant com.TypeEnum.0]

编辑进一步分析发现问题不在于枚举,而是parameterObj.properties = params执行时,parameterObj.validate()返回false。

在我的 Grails 2.5 代码中,

parameterObj.validate()   //returns true

parameterObj.properties = params
// code to convert String from params to Enum object and assign it to parameterObj
parameterObj.enumField = MyEnumClass.getEnumByName(params.enumNameValue)
parameterObj.validate()   //This always return false

注意:以上两种validate()的情况,parameterObj的字段值是完全一样的

在 Grails 2.5 中使用域类的属性有什么变化吗?

【问题讨论】:

  • 您能否提供失败字段的域类属性定义,以及参数中键/值的打印输出?如果错误仍然是发布的ValidationError,那么grails显然会尝试将字符串“0”写入TypeEnum字段,这当然会失败,因为字符串值需要转换为TypeEnum
  • 是的,Grails 不会接受 TypeEnum 的“0”。因此,在验证之前,我将“0”转换为枚举对象并将其分配给域对象。将上面的代码编辑得更具体

标签: grails enums grails-2.0 grails-domain-class


【解决方案1】:

如果您更改视图,以便它们将枚举的 name() 作为参数值发送,则数据绑定可以开箱即用。

至少我一直都是这样使用枚举的。

使用 name() 的枚举数据绑定

<g:select name="typeEnum" from="${TypeEnum.values()}" value="${obj.typeEnum}"/>

grails 然后使用每个枚举值的 .name() 作为值,使用 .toString() 作为显示的文本。这将生成如下内容:

<select name="typeEnum">
  <option value="STRING">String</option>
  <option value="NUMBER">Number</option>
  ...
</select>

控制器中的数据绑定可以很好地与域或命令对象一起工作:

def save1(PsparameterCmd cmd) {
  ...
  instance.properties = cmd.properties
}
def save2() {
  ...
  instance.properties = params
}

自定义枚举数据绑定

或者,您可以使用自定义数据绑定将 ID 转换为枚举值。

有不同的方法(文档:http://docs.grails.org/2.5.0/guide/theWebLayer.html#dataBinding): * 您可以为该类型注册一个全局数据绑定器(如果您在应用程序中经常使用该枚举) * 您可以在该单个字段上指定一个 dataBinding 注释(用于单次使用)

class Psparameter implements java.io.Serializable {
  @BindUsing({ obj, params ->
    return TypeEnum.values().find({ it.id == params.int('typeId') })
  })
  TypeEnum typeEnum
  ...
}

或全局转换器:

import org.grails.databinding.converters.ValueConverter
class TypeEnumConverter implements ValueConverter {
  boolean canConvert(value) {
    value instanceof Integer
  }
  def convert(value) {
    return TypeEnum.values().find({ it.id == value })
  }
  Class<?> getTargetType() {
    TypeEnum
  }
}

你必须在 resources.groovy 中注册

beans = {
  typeEnumConverter(your.package.TypeEnumConverter)
}

注意:据我所知(并且刚刚测试过),没有像 TypeEnum.getTypeEnumById(value) 这样的通用方法。这就是为什么我在上面的示例中使用 TypeEnum.values() 上的查找。

【讨论】:

  • 感谢 norganos 的输入,经过进一步分析,我发现问题不在于枚举,而在于使用域上的属性。请参考我的问题中的编辑
  • 午饭后我去看看 ;-)
【解决方案2】:

经过一段时间的努力,我在 Grails 2.5 中找到了解决这种行为的方法。这是我的解决方案和观察。再次粘贴我的问题代码以供参考:

parameterObj.validate()   //returns true

 parameterObj.properties = params
// code to convert String from params to Enum object and assign it to parameterObj
parameterObj.enumField = MyEnumClass.getEnumByName(params.enumNameValue)
parameterObj.validate()   //This always return false
  1. 如果一个字段(如我的示例中的 enumField)是一个枚举,那么枚举字符串值应该被传递给域对象(parameterObj)而不是枚举对象。 例如,如果我的枚举是

     enum TypeEnum {
        STRING(0, "String"), NUMBER(1, "Number"), TIME(2, "Time")
         ...
       }
    

那么要发送到 domainObj 的值为“STRING”或“NUMBER”等

  1. 在我的情况下,如果我在将参数分配给属性后使用“STRING”更新 enumField,那么 validate 仍然返回 false。例如,

     parameterObj.properties = params
     parameterObj.enumField = "STRING"
     parameterObj.validate()  // returns FALSE
    

    所以我必须在执行 parameterObj.properties = params 之前更新 params 中的 enumField 以通过 validate() 方法获得正确的结果。所以下面这个序列中的代码可以正常工作。

     params.enumField = "STRING"
     parameterObj.properties = params
     parameterObj.validate()  // returns True as expected
    

    早期版本的 Grails 并非如此,我的应用程序在 Grails 版本 1.3.3 上运行良好多年

【讨论】:

    猜你喜欢
    • 2013-09-20
    • 2012-02-11
    • 2013-05-10
    • 2011-12-13
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    • 2011-06-09
    • 1970-01-01
    相关资源
    最近更新 更多