【发布时间】:2013-03-07 16:18:42
【问题描述】:
人们使用什么技术有效地对大量类进行级联删除?
假设我有以下域类:
class Submission {
static hasMany = [members: Member]
}
class Member {
static belongsTo = [submission: Submission]
static hasMany = [events: Event, hashCodes: HashCode]
}
class Event {
static belongsTo = [member: Member]
}
class HashCode {
static belongsTo = [member: Member]
}
现在,给定提交的成员数量可能非常大,例如 100,000+,但这绝不是有限的。事件和哈希码是每个成员 15 个。
我需要删除给定提交的部分或全部成员(我们现在假设所有成员),但保留提交记录不变。所以我目前这样做如下:
Set<Member> membersToDelete = Member.findAllBySubmissionId( submission.id )
withSessionCleaner(membersToDelete){ member ->
submission.payroll.removeFromMembers( member )
member.delete( failOnError: true )
}
其中一些通用基础服务提供会话清理器:
SessionFactory sessionFactory
def propertyInstanceMap = org.codehaus.groovy.grails.plugins.DomainClassGrailsPlugin.PROPERTY_INSTANCE_MAP
private static final int DEFAULT_SESSION_CLEANER_CHECKPOINT = 100
def withSessionCleaner(def items, Closure c)
{
items.eachWithIndex { obj, index ->
c(obj)
if (++index % DEFAULT_SESSION_CLEANER_CHECKPOINT == 0) {
def session = sessionFactory.currentSession
session.flush()
session.clear()
propertyInstanceMap.get().clear()
}
}
}
会话清理方法是必需的,否则 Grails 会将所有对象保留在会话缓存中,最终我会出现内存不足问题和/或处理开始需要很长时间才能接近集合结束。
我对这种方法的主要担忧是:
- Grails 为 Member/Event/HashCode 类从数据库读取或加载到内存中的是什么?我听说过延迟加载,但不知道如何在这 3 个类上检查或配置它。
- 单独处理每个成员似乎对于级联删除工作是必要的,但对于我想要实现的目标来说似乎可能很昂贵。
我可以运行一些 SQL 查询来实现我的目标吗:
- delete from Event where member_id in (select id from Member where submit_id = ?)
- 从 HashCode where member_id in 中删除(select id from Member where submit_id = ?)
- delete from Member where submit_id = ?
但现在我使用的是原始 SQL,并没有真正使用 Grails 类或关系。是否存在等同于这些 SQL 语句的 Grails/GORM 命令?
有什么建议吗?
【问题讨论】:
标签: mysql grails grails-orm