私はGrailsでこれに似たツリー構造を持っています:
class TreeNode {
String name
// more properties
List children = []
static hasMany = [children: TreeNode]
static belongsTo = [parent: TreeNode, root: TreeNode]
static mappedBy = [children:'parent']
static constraints = {
name(blank: false,maxsize: 100,)
parent(nullable:true)
root(nullable:false)
}
}
SQL のパフォーマンス上の理由から、各レコードがそのルート ノードを直接参照する必要があります。したがって、「ルート」プロパティ。
「ルート」を追加する前は、ノードは正しく保存されていました。つまり、ルート ノードで save() を呼び出すことができ、parent_id フィールドがすべてのノードで適切に割り当てられました (親 ID が null のままであるルート自体を除く)。
親が見つかるまでツリーを上にたどって、 beforeInsert() で「ルート」を割り当てようとしました。
def beforeInsert = {
def node = this
while (node.parent) {
node = node.parent
}
root = node
}
定期的にスタック オーバーフローの例外が発生します。
at org.codehaus.groovy.grails.orm.hibernate.validation.HibernateDomainClassValidator.cascadeValidationToOne(HibernateDomainClassValidator.java:116)
at org.codehaus.groovy.grails.validation.GrailsDomainClassValidator.cascadeToAssociativeProperty(GrailsDomainClassValidator.java:142)
スタック オーバーフロー例外が発生しない場合、各「ルート」は最終ルートではなく自身を参照します。beforeInsert() はツリーを登っていません。
この問題を分解するのを手伝ってくれませんか? GORM はツリー構造を深さ優先で保存しようとしますか? その場合、親がまだ永続化されていない場合、親 ID をどのように保存しますか? 最も重要なことは、ルート ノードで save() を呼び出してツリーを保存するにはどうすればよいかということです。そのような「ルート」は、save() の後ですべてのノードを (すぐに) 更新する必要なく適切に設定されますか?