0

人们使用什么技术来有效地对大量类进行级联删除?

假设我有以下域类:

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 会将所有对象保留在会话缓存中,最终我会出现内存不足问题和/或处理开始需要很长时间才能接近集合结束。

我对这种方法的主要担忧是:

  1. 什么是 Grails 从数据库读取或加载到 Member/Event/HashCode 类的内存中?我听说过延迟加载,但不确定如何在这 3 个类上检查或配置它。
  2. 单独处理每个成员似乎对于级联删除工作是必要的,但对于我想要实现的目标来说似乎可能很昂贵。

我可以运行一些 SQL 查询来实现我的目标吗:

  1. 从其中 member_id 的 Event 中删除(从 Member where submit_id = 中选择 id)
  2. 从 HashCode where member_id in (select id from Member where submit_id = ?) 中删除
  3. 从成员中删除 submit_id = ?

但现在我使用的是原始 SQL,并没有真正使用 Grails 类或关系。是否存在等同于这些 SQL 语句的 Grails/GORM 命令?

有什么建议么?

4

1 回答 1

0

最快的方法是在子对象上使用 ON DELETE CASCADE 创建 FOREIGN KEYS(希望您的数据库允许您这样做)。之后,您可以按 ID 安全地删除成员,数据库将完成剩下的工作。

于 2013-03-08T20:24:17.980 回答