当使用数据绑定更新多对多关系时,索引越界



我在更新具有多对多关系的域时遇到问题。例如,考虑这两个简单的域。

class Student {
   String name
   static hasMany = [courses: Course]
}
class Course {
  String name
  static hasMany = [students: Student]
  static belongsTo = [Student]
}

为了更新学生的姓名和他/她的课程名称,我使用这样的数据绑定:

def params = [
  'courses[0].id': c2.id,
  'courses[0].name': 'c11',
  'courses[1].id': c1.id,
  'courses[1].name': 'c22'
]
s1.properties = params
s1.save(flush: true)

然而,这将导致错误:

org.springframework.beans.InvalidPropertyException: Invalid property 'courses[1]' of bean class [tb.Student]:
Invalid list index in property path 'courses[1]'; nested exception is java.lang.IndexOutOfBoundsException:
Index: 1, Size: 1

经过一番搜索,我发现所有答案都建议使用List来表示关系,而不是Set。但是,我仍然更喜欢使用Set。

环境

  • 圣杯:2.2.3
  • Java:1.6.0_45
  • 操作系统:Ubuntu 13.04

我的解决方案是在数据绑定之前清除子列表。这是测试上述域的完整代码。线路s1.courses.clear()将防止上述错误。

def s1 = new Student(name: 's1').save(flush: true)
def s2 = new Student(name: 's2').save(flush: true)
def c1 = new Course(name: 'c1').save(flush: true)
def c2 = new Course(name: 'c2').save(flush: true)
s1.addToCourses(c1)
s1.addToCourses(c2)
s1.save(flush: true)
def params = [
  'courses[0].id': c2.id,
  'courses[0].name': 'c11',
  'courses[1].id': c1.id,
  'courses[1].name': 'c22'
]
s1.courses.clear()
s1.properties = params
s1.save(flush: true)

然而,我仍然认为这个问题是一个bug。我的解决方案是一个变通办法。

集合没有排序,因此如果指定索引,它将失败。

如果您不想使用List,请尝试使用SortedSet。

你可以找到更多信息@(http://grails.org/doc/latest/guide/single.html#ormdsl)6.5.3默认排序顺序

最新更新