如何管理一对多关系 - grails

时间:2013-06-05 02:08:59

标签: grails

我有一个简单的问题。我需要在域对象上管理hasMany集合。我以为我做得对,但它没有用。我找到了另一篇文章,但它已经过时且不起作用(Handling parameters from dynamic form for one-to-many relationships in grails

class User{
   static hasMany = ['prefs': Preference] 
}
class Preference{
  Boolean email
  Boolean site
  Date dateCreated
  Date lastUpdated

}

GSP

<g:each var="t" in="${user.prefs}" status="idx">            
  <li>
    <input type='hidden' name="prefs[${idx}].id" value="${t.id}"/>
    Email: <g:checkBox name="prefs[${idx}].email" value="${t.email}" />
    Site: <g:checkBox name="prefs[${idx}].site" value="${t.site}" /><
  </li>
</g:each>

控制器:

log.info(user.prefs)
user.properties = params
if(!user.save()){ ... }

然后出错:

  

UserController - [偏好:3,偏好:4]

   错误2013-06-04 21:54:41,405 [http-bio-8080-exec-12] ERROR errors.GrailsExceptionResolver

  处理请求时发生IndexOutOfBoundsException:[POST] / user / prefs - 参数:   首选项[0] .email:
  id:2
  prefs [1] .site:on
  prefs [0] .email:on
  _prefs [1] .site:
  _prefs [1] .email:
  prefs [1] .id:3
  _prefs [0] .site:
  prefs [0] .site:on
  prefs [0] .id:4
  索引:1,大小:1。Stacktrace如下:
  消息:索引:1,大小:1


2 个答案:

答案 0 :(得分:1)

前几天我发现了这个问题。并花了2天时间来解决它。

您必须确保params中的子索引与父对象的顺序相同。在这种情况下,孩子的顺序是[偏好:3,偏好:4]。但params顺序是prefs [0] .id = 4,prefs [1] .id = 3.顺序不同。

我必须在绑定它们之前对参数中的子索引重新排序。

答案 1 :(得分:0)

所以我最终解决了这个问题,这是一种混合方法。 @Meam是正确的,这是一个排序问题,但不是担心排序我只是使用@dmahapatro的方法并将Preference设置为一个列表。关于这一点的附注是List preference的定义必须在static hasMany定义之前。或者在尝试创建用户时会出现随机错误。最后,当您最初设置关系时,您必须使用addTo链接两个...

class User{
  List preference
  static hasMany = ['prefs': Preference] 
}

//another thing I did not know in order to originaly link 
//the two when using lists, you have to use addTo...
user.addToPrefs(
    new Preference(email: true, site:false)
)

我想提到的最后一件事是<g:checkbox>中存在一个错误,如果您将其与hasMany一起使用,就像我尝试取消选中该值一样,它将无效。我能够通过处理来自FormTagLib的github的代码来解决这个问题。然后用另一篇文章更新了代码我正在阅读https://stackoverflow.com/a/2942667/256793,它有一个解决方案,但它有点过时了。所以这是更新版本:

 //old code
 //out  << "<input type=\"hidden\" name=\"_${name}\""
 //new...
 def begin =  name.lastIndexOf('.') +1
 def tail =  name.substring( begin);
 out << "<input type=\"hidden\" name=\"${name.replace(  tail, "_" + tail  )}\" "