クラスの大規模なコレクションに対してカスケード削除を効率的に行うために、人々はどのような手法を使用していますか?
次のドメイン クラスがあるとします。
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 以上になる可能性がありますが、これに制限はありません。イベントと HashCodes は、メンバーごとに 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 がセッション キャッシュ内のすべてのオブジェクトを保持し、最終的にメモリの問題が発生したり、コレクションの終わりに向かって処理に時間がかかり始めたりするため、セッション クリーナー メソッドが必要です。
このアプローチに関する私の主な懸念事項は次のとおりです。
- Member/Event/HashCode クラスの Grails が db からメモリに読み込んだりロードしたりするのは何ですか? 遅延読み込みについて聞いたことがありますが、これら 3 つのクラスでこれを確認または構成する方法がわかりません。
- カスケード削除が機能するには、各メンバーを個別に処理する必要があるようですが、私が達成しようとしていることには潜在的にコストがかかるようです。
私が何を達成するためにいくつかのSQLクエリを実行できますか:
- member_id の Event から削除 (submission_id = ? の Member から ID を選択)
- member_id の HashCode から削除 (submission_id = ? の Member から ID を選択)
- submit_id = ? のメンバーから削除します。
しかし今、私は未加工の SQL を使用しており、Grails のクラスや関係を実際には使用していません。これらの SQL ステートメントと同等の Grails/GORM コマンドはありますか?
助言がありますか?