如何在Grails / Groovy中以一对多关系清除和替换集合

时间:2010-01-15 15:33:23

标签: grails gorm

这个问题分为两个部分,第一部分是关于清除列表,第二部分是关于将所有者分配给一个对象。

我在Grails的模型中有两个域对象之间的一对多关系。这种关系看起来像这样......

class Person {

    static hasMany = [authorities: Role, locations: Location]
}

class Location {

    static belongsTo = Person

}

在我的应用中,locations上的Person列表会被完全刷新,并替换为用户操作的新列表。更重要的是,我得到的Location个对象列表独立于关联的Person。我通过检索当前登录的用户来解析应用它们的人,我称之为activePerson并且可以用于我的目的。

我要做的是删除activePerson上的所有现有位置,然后插入所有新位置,并将其与activePerson相关联。我在Person上有很多属性,我不想在此时保留这些属性,因此我想避免保存整个父对象,因为子位置已经更改。

我想迭代遍历activePerson.locations列表并逐个删除它们并依赖GORM / Hibernate将查询批处理并最后刷新。这似乎是蛮力,虽然它可能有用。我期待有一个clearLocations方法或类似的方法,但我找不到一个。

如果我只是用新列表替换activePerson.locations并调用activePerson.save(flush:true),GORM会处理删除现有行吗?

其次,我想将新的Location个对象放到activePerson上。我可以再次填充activePerson.locations并保存整个内容,但如果可以,我想避免这样做。我可以单独保存它们,但是如何在我去的时候在每个belongsTo对象上设置Location

所以回顾一下:

  1. 如何在一对多集合的多端清除列表?
  2. 如何将独立对象与父对象关联并单独保留它们?
  3. 由于

4 个答案:

答案 0 :(得分:9)

清除Collection方法对我没有用处:

activePerson.locations.clear()

尝试通过调用ConcurrentModificationException

来避免collect()迭代收集
activePerson.locations.collect().each {
    item.removeFromLocations(it)
}

然后保存实体以执行SQL语句:

activePerson.save flush:true

链接到文章阅读更多内容: http://spring.io/blog/2010/07/02/gorm-gotchas-part-2/

答案 1 :(得分:8)

对于#1,您可以清除集合(默认情况下为Set):

activePerson.locations.clear()

对于#2,请使用addToLocations:

activePerson.addToLocations(location)

当您保存此人时,位置< - >人员关系将会更新。

答案 2 :(得分:7)

虽然这是一个较旧的问题,但我遇到了一个非常类似的情况,我想更新一组子记录。以下是我选择解决问题的方法。为简单起见,我将使用与问题提问者相同的对象/关系名称。

  1. 在父域的mapping块中,添加:

    static mapping = {
        locations(cascade: "all-delete-orphan")
    }
    
  2. 在子域中,添加@EqualsAndHashCode注释(以防万一其他人潜伏,我指的是groovy.transform.EqualsAndHashCode)。

  3. 使用Grails addTo方法(例如addToLocations)将所有子元素添加到父域,然后保存父域。

  4. 虽然这种方法确实需要保存父域(提问者不想这样做),但鉴于模型中明确的belongsTo定义,它似乎是最合适的方法。因此,我会回答提问者编号的问题:

    1. 不要手动执行,而是让Grails / Hibernate通过在关系上指定all-delete-oprhan级联行为来清除记录。

    2. 不要尝试直接保存子记录,而是保存父对象以匹配Grails的预期。

答案 3 :(得分:0)

这对我有用:

activePerson.locations.clear()
activePerson.properties = params

...

activePerson.save()

这将清除位置集,然后仅添加当前在参数中选择的位置。