提问人:Simon 提问时间:2/10/2010 更新时间:10/24/2013 访问量:36609
如何在 Grails/GORM 中批量删除记录?
How do you bulk delete records in Grails/GORM?
问:
我有一个表格,其中包含需要根据一组标准定期清除的记录。
我本来以为我可以使用条件生成器来删除记录,但这失败了,因为没有关于条件的方法......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 中执行,但这感觉也是错误的。条件生成器是否仅用于检索?
谢谢
答:
19赞
Colin Harrington
2/10/2010
#1
请注意,Grails 没有提供 deleteAll 方法,因为删除数据是 气馁,通常可以避免 通过布尔标志/逻辑。
如果确实需要批量删除 可以使用 executeUpdate 的数据 批量 DML 语句的处理方法:
Customer.executeUpdate("delete Customer c where c.name = :oldName", [oldName:"Fred"])
评论
24赞
Simon
2/10/2010
是的,这就是我的做法,但是我不能使用标准有点疯狂。DELETE 是查询语义的有效部分,并得到所有 RDBMS 的支持,并且是完全有效的事情,尽管 Hibernate/GORM 作者可能怎么想。就我而言,将过期的记录留在表中是非常糟糕的做法。
1赞
Colin Harrington
3/15/2014
正如 JesperSM 所引用的: 现在 Grails 2+ 在 DetachedCriteria 上确实有一个 deleteAll()。
3赞
A.W.
4/17/2014
这行得通。但是,太糟糕了,它不会级联删除子表中的行。然后它给出一个 .在 中对此进行了测试。Integrity constraint violation
2.3.7
1赞
Christof
10/2/2014
我们遇到了与@Guus相同的问题。在内部,JDBCPreparedStatement 用于执行更新,这显然不遵守 Hibernate 或其实体关系的级联规则。
0赞
Badri Paudel
3/1/2022
@Simon我知道这种类型的解决方案有效,但这对于解决方案删除大量数据有效吗?假设我想删除 10K 数据,这样可以吗?
13赞
sbglasius
2/10/2010
#2
如果你想避免 HQL,我建议使用 GORM list()、delete() 和 Groovy 的 spread 运算符:
def agencyList = Agency.createCriteria().list { eq("agency", "XXX") } agencyList*.delete()
评论
1赞
Simon
2/11/2010
哇!那个流浪的*有什么作用?我完全尝试了这个,但没有 * 并得到编译器错误......
2赞
Colin Harrington
2/11/2010
这*。是 Groovy 扩展运算符 groovy.codehaus.org/Operators#Operators-SpreadOperator(.)在 Sbgrasius 的示例中,它对返回的集合中的项调用 delete() 方法。
0赞
khylo
3/15/2012
使用此方法时,我遇到了java.util.ConcurrentModificationException...因此,我停止使用扩展运算符,并按照 stackoverflow.com/questions/1816196/ 中的解决方案使用迭代器创建了一个while循环......
15赞
JesperSM
4/23/2012
这样做的问题是,您最终会获取整个集合,并线性删除每个集合。这意味着整个表都进入了堆,这对于玩具模型来说不是问题,但对于真正的批量数据来说可能是问题。
0赞
Dhaval dave
8/27/2015
也解决了我的问题:,当我们得到带有用途的列表时。FindAllBy*,要删除所有用户,需要用户*.delete()谢谢@sbglasius
50赞
JesperSM
4/23/2012
#3
在 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 单元测试模拟有很多陷阱,但总体上非常整洁。
评论
0赞
Peter
5/24/2012
这似乎是最好的肯定。我正在使用它。
1赞
GreenGiant
2/11/2014
Grails 文档:grails.org/doc/latest/guide/single.html#whereQueries
0赞
Alexander Suraphel
7/16/2015
Jesper,我完全同意“GORM 单元测试模拟有一堆陷阱”。他们被记录在什么地方?
0赞
Tung
11/17/2018
正如我所尝试的那样,该解决方案运行良好且可靠。
评论