Древовидная структура в Горме (граали)
Я пытаюсь определить древовидную структуру в GORM. Вот моя модель:
class Tree {
String name
Level rootLevel
static hasOne = [rootLevel: Level]
static hasMany = [levels: Level]
static mappedBy = [levels:"parentTree"]
}
class Level {
String name
Tree parentTree
Level parentLevel
Set<Level> subLevels
static belongsTo = [parentTree: Tree]
static hasMany = [subLevels: Level]
}
Вставка, кажется, работает нормально, но когда я не могу загрузить дерево со многими уровнями и подуровнями.
Наверное, я что-то упустил в отношениях:
- дерево должно иметь ссылку на корневой уровень (и необязательно на все подуровни)
- уровень должен иметь ссылку на его Родительский уровень, его подуровни и глобальное родительское дерево
Не могли бы вы указать мне правильное направление, чтобы получить такую древовидную структуру, как эта ? Спасибо
3 ответа:
Мне не понравилась ваша древовидная структура, поэтому я создал свою собственную :)
Class TreeNode { String name TreeNode parent static hasMany = [children: TreeNode] //returns the root node, and by extension, the entire tree! TreeNode getRootNode(){ if(parent){ //if parent is not null then by definition this node is a child node of the tree. return parent.getRootNode() }else{ //if parent is null then by definition it is the root node. return this } } //you might not need this function, but ill add it as it is common in tree structures boolean isLeaf(){ //determines if this node is a leaf node. a leaf is a node with zero childrens return children.isEmpty() } }
Что касается обеспечения загрузки всех treenodes, вы всегда можете использовать нетерпеливую/не ленивую выборку для каждого treeNode как родительского, так и дочернего. Однако это может привести к снижению производительности, если ваши древовидные структуры очень велики...
А для нетерпеливых/ленивых выборки. посмотрите здесь: Использование ленивой выборки свойств в Grails / Gorm
Проблема заключается в том, что уровни заполняются идентификатором родительского дерева, но при загрузке дерева возникает следующая ошибка "для класса Level найдено более одной строки с заданным идентификатором".
Ваша проблема, похоже, заключается в том, что у вас есть более одного корневого узла для каждого дерева. Это необычный подход. Чтобы заставить его работать, вы должны заменить
Level rootLevel
в сущностиTree
наSet<Level> roots
.
Я пришел к такому решению (спасибо другу):
class Tree { String name Level rootLevel static hasMany = [levels: Level] static mappedBy = [rootLevel: "parentTree", levels: "owningTree"] static constraints = {rootLevel(nullable: true)} }
И
class Level { String name Tree parentTree Tree owningTree Level parentLevel Set<Level> subLevels static belongsTo = [owningTree: Tree, parentLevel: Level] static hasMany = [subLevels: Level] static mappedBy = [parentTree: "rootLevel", owningTree: "levels", subLevels: "parentLevel"] static constraints = { parentTree(nullable: true) parentLevel(nullable: true) } }
Мне не хватало двух отношений между деревом и уровнем (owningTree и parentTree) и некоторой конфигурации mappedBy, помогающей гибернации.