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

Posted

技术标签:

【中文标题】如何批量删除 Grails/GORM 中的记录?【英文标题】:How do you bulk delete records in Grails/GORM? 【发布时间】:2011-01-15 00:19:35 【问题描述】:

我有一个表,其中包含需要根据一组标准定期清除的记录。

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

def c = Agency.createCriteria()
c.delete

    eq("agency", "XXX")  

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

def c = Agency.createCriteria()
def deletions = c

    eq("agency", "XXX")  

deletions.delete

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

那么正确的方法是什么?我必须遍历整个结果集,在每个项目上调用delete(),这似乎有点过分(不正常)。

我知道我可以形成一个查询以直接在 HQL 或 SQL 中执行,但这也感觉不对。标准构建器是否仅用于检索?

谢谢

【问题讨论】:

【参考方案1】:

在 Grails 2.0 中,您可以像这样使用分离查询:

Agency.where  .deleteAll()

请注意,您不会执行侦听器和其他操作,但它会执行到数据库,并且它与模拟的域内容兼容,如下所示:

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

    Agency.where  .deleteAll()

    assert Agency.count() == 0   // Joy!

话虽如此,GORM 单元测试模拟有很多陷阱,但总的来说非常简洁。

【讨论】:

这似乎是最好的。我正在使用它。 Grails 文档:grails.org/doc/latest/guide/single.html#whereQueries Jesper,我完全同意“GORM 单元测试模拟有很多陷阱”。它们记录在什么地方? 正如我所尝试的那样,此解决方案运行良好且可靠。【参考方案2】:

来自User Guide about deleting objects:

请注意,Grails 不提供 删除数据的 deleteAll 方法是 气馁,通常可以避免 通过布尔标志/逻辑。

如果确实需要批量删除 可以使用 executeUpdate 的数据 批量 DML 语句的方法:

Customer.executeUpdate("delete Customer c where c.name = :oldName", [oldName:"Fred"])

【讨论】:

是的,我就是这样做的,但是我不能使用标准有点疯狂。 DELETE 是查询语义的有效部分,并受到所有 RDBMS 的支持,并且是一件完全有效的事情,尽管 Hibernate/GORM 作者可能会这么想。在我的情况下,将过期记录留在表中是非常糟糕的做法。 作为 JesperSM 引用:现在 Grails 2+ 在 DetachedCriteria 上有一个 deleteAll()。 这行得通。但是太糟糕了,它不会级联删除子表中的行。然后它给出一个Integrity constraint violation。在2.3.7 中对此进行了测试。 我们遇到了与@Guus 相同的问题。在内部,JDBCPreparedStatement 用于执行更新,这显然不符合 Hibernate 或其实体关系的级联规则。【参考方案3】:

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

def agentList = Agency.createCriteria().list eq("机构", "XXX") 代理列表*.delete()

【讨论】:

哇!那个流浪*做什么?我尝试了这个但没有 * 并得到一个编译器错误...... *.是 Groovy 扩展运算符 groovy.codehaus.org/Operators#Operators-SpreadOperator(.) 在 Sbglasius 的示例中,它对返回的集合中的项目调用 delete() 方法。 我在使用此方法时遇到了 java.util.ConcurrentModificationException...所以我停止使用扩展运算符并使用迭代器创建了一个 while 循环,按照***.com/questions/1816196/…中的解决方案@ 这样做的问题是您最终会获取整个集合,并线性删除它们中的每一个。这意味着整个表都进入了堆,这对于玩具模型来说不是问题,但对于真正的大容量数据来说可能是个问题。 也解决了我的问题:当我们使用 uses.FindAllBy* 获取列表时,要删除所有用户,您需要 user *.delete() 谢谢@sbglasius

以上是关于如何批量删除 Grails/GORM 中的记录?的主要内容,如果未能解决你的问题,请参考以下文章

Grails/GORM 中的错误:已删除的对象将被级联重新保存

独立使用 Grails GORM

如何在 Grails/GORM 中将派生属性设置为小写?

Grails + GORM:GORM 中默认的 equals() 实现是啥?

命名查询中的 Grails GORM 计数函数

在 Grails (GORM) 中处理并发修改,同时避免过时对象异常