Grails 2.4.4升级数据绑定问题

时间:2015-01-15 19:20:10

标签: grails data-binding upgrade

我们在这里用于大型动态表单的模式是允许客户端编辑几乎整个图形,包括子项,并且在javascript中处理删除和添加子项。失败的用例是当用户删除其中一个孩子的属性时,对于这个例子,我们会说第二个孩子的电子邮件地址被删除,并且parm被发送为空。

示例类结构

域X

  Long id
  String name
  SortedSet<Child> children

域名儿童

  Long id
  Integer position // used to sort 
  String name (required)
  String email (required)

Parms以这种方式命名:

 x.id = 1
 x.name = 'blah'
 x.children[0].id = 1
 x.children[0].position = 0
 x.children[0].name = 'childa0'
 x.children[0].email = 'child0@any.com'
 x.children[1].id = 2
 x.children[1].position = 1
 x.children[1].name = 'child1'
 x.children[1].email = ''

当前存储的值:

 x.id = 1
 x.name = 'blah'
 x.children[0].id = 1
 x.children[0].position = 0
 x.children[0].name = 'childa0'
 x.children[0].email = 'child0@any.com'
 x.children[1].id = 2
 x.children[1].position = 1
 x.children[1].name = 'child1'
 x.children[1].email = 'child1@any.com'

要更新的模式是:

浏览器

  • 用户编辑所有内容并提交更改
  • parms如上所示发送,在此用例中,用户意外删除了所需的电子邮件地址(在这种简单的情况下可以阻止提交,但是有更广泛的验证规则,这只是一个简单的例子来说明问题)

服务器

  • 使用id parm
  • 检索当前的父域类
  • 根据已编辑的版本检查当前存储的版本并确保其未更改
  • 以这种方式将所有参数应用于当前域对象:x.properties = parms.x

这是它崩溃的地方。使用Grails 2.2.2,子[1]的email属性更新为空字符串,运行验证捕获错误。 Grails 2.4.4不会更新子值。我知道数据绑定发生了变化,也许这种变化有正当理由,但我无法理解。这从1.3.6到2.2.2有效。

有一点需要注意的是,如果我没有检索域类,而是创建一个新实例,并且所有子parms中传递的parms都已正确设置。

X x = new X(params.x) 

这似乎表明了一些Grails问题,因为用户指南将两种方法都视为相同 - 一种用于新实例,另一种用于更新,但示例清楚地表明两种方法都应该处理索引的子属性。

感谢任何帮助或想法!

4 个答案:

答案 0 :(得分:2)

我遇到了这个问题,我自己将应用程序从2.2.4升级到2.4.4。

config.groovy

设置 grails.databinding.useSpringBinder = true

grails-web-databinding-spring 添加到 pom 对我来说是完美无缺的。

显然,这样做比重写所有绑定代码要麻烦得多: - )

答案 1 :(得分:1)

进一步研究Grails 2.4.4文档说明,如果它们被索引(即[0]),它将按位置绑定集合。

http://grails.org/doc/latest/guide/single.html#dataBinding

标题为“数据绑定和多端关联”的部分指出这些参数将被绑定,并且如果它们的索引大于当前集,则将创建该集的新实例。在Grails 2.2.2中我是这样,但在2.4.4中则不然。

然而,在“绑定到集合和映射”一节的文档中,它清楚地说明:“当更新集合中的现有元素时,分配给集合的映射必须包含表示元素的元素。集”。

如果您要升级到Grails 2.4.4并且有任何复杂的表单数据绑定,我建议您先查看是否要升级。由于数据绑定的这些变化,这已经成为我们在Grails中遇到的最复杂的升级。

对2.4.4的另一个失望是,它声明你可以覆盖新的绑定并回退到旧的弹簧绑定,但你不能超过2.4 - 至少从我可以从别人的帖子和我的尝试收集。按文档设置config属性并添加所需的依赖项会导致启动运行时错误。

答案 2 :(得分:0)

显然,2.4.4之前的旧版本grails会将子实例与params匹配,即使用索引([0],[1]等)来匹配不关心实例ID的子项匹配。新绑定程序确实希望在绑定之前匹配实例的ID。我从来没有意识到我没有把ID放在隐藏的领域,因为它总是很完美。

答案 3 :(得分:0)

迁移到Grails 2.4.4(从2.2.2开始)后,我遇到了类似的问题。经过大量阅读和搜索(你必须明确阅读用户邮件中的http://docs.grails.org/2.4.4/guide/single.html#dataBinding帖子)我已经以一种非常简单的方式解决了这个问题

在我的应用程序中,我有嵌套的域关系。例如:

class A {
String name
static hasMany = [b:B]
}

class B {
String name
static hasMany = [c:C]
}

class C {
String name
}

由于表单的复杂性,C类对象没有正确绑定。我已经解决了将B类中的C属性定义为List的问题(请记住,默认情况下,许多关系都实现为Set)。所以,我的B班改为:

class B {
String name
static hasMany = [c:C]
List c
}

瞧!一切都完美无缺。