如何批量删除 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 中的错误:已删除的对象将被级联重新保存