如何批量删除Grails/GORM中的记录?

Sim*_*mon 23 grails hibernate grails-orm

我有一张表,其中有记录需要根据一组标准定期清除.

我原以为我可以使用条件构建器来删除记录,但由于delete条件上没有方法,因此失败了...

def c = Agency.createCriteria()
c.delete
{
    eq("agency", "XXX")  
}
Run Code Online (Sandbox Code Playgroud)

所以我想也许我首先查询该集合然后删除...

def c = Agency.createCriteria()
def deletions = c
{
    eq("agency", "XXX")  
}
deletions.delete
Run Code Online (Sandbox Code Playgroud)

这也因同样的原因,不同的对象而失败.

那么这样做的正确方法是什么?似乎过度(反常),我将不得不遍历调用delete()每个项目的整个结果集.

我知道我可以形成一个查询,直接在HQL或SQL中执行,但这也是错误的.标准构建器仅用于检索吗?

谢谢

Jes*_*rSM 50

使用Grails 2.0,您可以使用这样的分离查询:

Agency.where { }.deleteAll()
Run Code Online (Sandbox Code Playgroud)

请注意,您没有获取侦听器以及执行的内容,但它确实执行到数据库,并且它与模拟的域内容兼容,如:

void testWhatever() {
    mockDomain(Agency, [])
    saveABunchOfAgencies() // saves 10 of 'em
    assert Agency.count() == 10

    Agency.where { }.deleteAll()

    assert Agency.count() == 0   // Joy!
}
Run Code Online (Sandbox Code Playgroud)

据说GORM单元测试嘲笑有一堆陷阱,但一般都非常整洁.


Col*_*ton 19

从" 用户指南"中删除对象:

请注意,Grails不提供deleteAll方法,因为不鼓励删除数据,并且通常可以通过布尔标志/逻辑来避免.

如果确实需要批量删除数据,可以使用executeUpdate方法执行批处理DML语句:

Customer.executeUpdate("delete Customer c where c.name = :oldName", [oldName:"Fred"])
Run Code Online (Sandbox Code Playgroud)

  • 是的,这就是我这样做的方式,但我不能使用标准有点疯狂.DELETE是查询语义的有效部分,并且受到所有RDBMS的支持,并且完全有效,尽管Hibernate/GORM作者可能会想到这一点.在我的情况下,将过时的记录留在表中是非常糟糕的做法. (22认同)
  • 这有效.太糟糕了,但它没有级联删除子表中的行.然后它给出了"完整性约束违规".在`2.3.7`中测试过. (3认同)

sbg*_*ius 13

如果你想避免使用HQL,我建议使用GORM list(),delete()和Groovy的扩展运算符:

def agencyList = Agency.createCriteria().list {
    eq("agency", "XXX")  
}
agencyList*.delete()

  • 这样做的问题是你最终获取整个集合,并线性删除它们中的每一个.这意味着整个表进入堆,这对于玩具模型来说不是问题,但可以用于真正的批量数据. (14认同)
  • 这 *。是 Groovy 展开运算符 http://groovy.codehaus.org/Operators#Operators-SpreadOperator(.) 在 Sbglasius 的示例中,它对返回的集合中的项目调用 delete() 方法。 (2认同)