简体   繁体   English

使用级联删除子类对域类进行Grails高效的批量删除

[英]Grails efficient batch delete on domain class with cascade delete to child classes

What techniques are people using to efficiently do cascading delete on a large collection of classes? 人们使用什么技术对大量的类进行级联删除?

Suppose I have the following domain classes: 假设我具有以下域类:

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]
}

Now the number of Members for a given Submission could be very large, say 100,000+, but this is no way limited. 现在,给定提交的成员数量可能非常大,例如100,000+,但这没有限制。 The Events and HashCodes would be say 15 per Member. 每个会员的事件和哈希码为15。

I need to delete some or all of the Members for a given Submission (let's assume all of them for now), but leave the Submission record intact. 我需要删除给定提交的部分或全部成员(现在让我们假设所有成员),但保持提交记录不变。 So I currently do this as follows: 所以我目前这样做如下:

Set<Member> membersToDelete = Member.findAllBySubmissionId( submission.id )
withSessionCleaner(membersToDelete){ member ->
   submission.payroll.removeFromMembers( member )
   member.delete( failOnError: true )
}

where some generic base service provide the session cleaner as: 其中一些通用基础服务为会话清洁器提供以下功能:

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()
        }
    }
}

The session cleaner method is required as otherwise Grails retains all objects in the session cache and eventually I get out of memory issues and/or the processing begins to takes a long time towards the end of the collection. 需要使用会话清除器方法,否则Grails会将所有对象保留在会话缓存中,并且最终我会遇到内存不足的问题,并且/或者处理过程在收集结束之前开始花费很长时间。

My main concerns with this approach are: 我对这种方法的主要担心是:

  1. What is Grails reading or loading from the db into memory for the Member/Event/HashCode classes? 对于Member / Event / HashCode类,Grails从数据库读取或加载到内存中的是什么? I've heard of lazy loading but not sure how to check or configure this on these 3 classes. 我听说过延迟加载,但是不确定如何在这3个类上进行检查或配置。
  2. Processing each Member seperately seems necessary for the cascade delete to work, but seems potentially expensive for what I'm trying to achieve. 单独处理每个成员似乎是级联删除工作所必需的,但对于我要实现的目标来说似乎很昂贵。

Could I run some SQL queries to achieve what I what: 我可以运行一些SQL查询来实现什么吗:

  1. delete from Event where member_id in (select id from Member where submission_id = ?) 从其中member_id所在的事件中删除(从Member中的submit_id =吗?
  2. delete from HashCode where member_id in (select id from Member where submission_id = ?) 从HashCode中删除member_id所在的位置(从Member中选择id,其中submitt_id =吗?)
  3. delete from Member where submission_id = ? 从会员中删除,其中commit_id =?

But now I'm in raw SQL and not really using the Grails classes or relationships. 但是现在我处于原始SQL中,并没有真正使用Grails类或关系。 Are there Grails/GORM commands that would equate to these SQL statements? 是否有Grails / GORM命令等同于这些SQL语句?

Any suggestions? 有什么建议么?

The fastest way is to create FOREIGN KEYS with ON DELETE CASCADE on child objects (hope your DB allows you to do it). 最快的方法是在子对象上使用ON DELETE CASCADE创建FOREIGN KEY(希望您的数据库允许您这样做)。 After that you can safely delete Members by ID, the database will do the rest. 之后,您可以安全地通过ID删除成员,其余的工作将由数据库完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM