2013-09-30 1 views
0

Я хочу создать древовидную структуру в Grails GORM. Структура должна быть контейнером для других объектов и должна полно заполнить следующие требования:Деревоподобная структура в Grails GORM

  • узел должен иметь от 0 до п детского
  • узел должен иметь ровно один родительский узел
  • узел должен иметь 0 до n родственных узлов

Как определить такую ​​структуру в Grails GORM?

Я попробовал следующий класс:

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

Но при запуске я получаю следующее сообщение об ошибке:

ERROR context.ContextLoader - Context initialization failed 
Message: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is org.codehaus.groovy.grails.exceptions.GrailsDomainException: Property [children] in class [class test.TreeNode] is a bidirectional one-to-many with two possible properties on the inverse side. Either name one of the properties on other side of the relationship [treeNode] or use the 'mappedBy' static to define the property that the relationship is mapped with. Example: static mappedBy = [children:'myprop'] 
    Line | Method 
->> 334 | innerRun in java.util.concurrent.FutureTask$Sync 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
| 166 | run  in java.util.concurrent.FutureTask 
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor 
| 615 | run  in java.util.concurrent.ThreadPoolExecutor$Worker 
^ 722 | run . . . in java.lang.Thread 
Caused by GrailsDomainException: Property [children] in class [class test.TreeNode] is a bidirectional one-to-many with two possible properties on the inverse side. Either name one of the properties on other side of the relationship [treeNode] or use the 'mappedBy' static to define the property that the relationship is mapped with. Example: static mappedBy = [children:'myprop'] 
->> 334 | innerRun in java.util.concurrent.FutureTask$Sync 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
| 166 | run  in java.util.concurrent.FutureTask 
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor 
| 615 | run  in java.util.concurrent.ThreadPoolExecutor$Worker 
^ 722 | run . . . in java.lang.Thread 
| Error 2013-10-04 17:36:00,730 [localhost-startStop-1] ERROR context.GrailsContextLoader - Error initializing the application: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is org.codehaus.groovy.grails.exceptions.GrailsDomainException: Property [children] in class [class test.TreeNode] is a bidirectional one-to-many with two possible properties on the inverse side. Either name one of the properties on other side of the relationship [treeNode] or use the 'mappedBy' static to define the property that the relationship is mapped with. Example: static mappedBy = [children:'myprop'] 
Message: Error creating bean with name 'pluginManager' defined in ServletContext resource [/WEB-INF/applicationContext.xml]: Invocation of init method failed; nested exception is org.codehaus.groovy.grails.exceptions.GrailsDomainException: Property [children] in class [class test.TreeNode] is a bidirectional one-to-many with two possible properties on the inverse side. Either name one of the properties on other side of the relationship [treeNode] or use the 'mappedBy' static to define the property that the relationship is mapped with. Example: static mappedBy = [children:'myprop'] 
    Line | Method 
->> 334 | innerRun in java.util.concurrent.FutureTask$Sync 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
| 166 | run  in java.util.concurrent.FutureTask 
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor 
| 615 | run  in java.util.concurrent.ThreadPoolExecutor$Worker 
^ 722 | run . . . in java.lang.Thread 
Caused by GrailsDomainException: Property [children] in class [class test.TreeNode] is a bidirectional one-to-many with two possible properties on the inverse side. Either name one of the properties on other side of the relationship [treeNode] or use the 'mappedBy' static to define the property that the relationship is mapped with. Example: static mappedBy = [children:'myprop'] 
->> 334 | innerRun in java.util.concurrent.FutureTask$Sync 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
| 166 | run  in java.util.concurrent.FutureTask 
| 1145 | runWorker in java.util.concurrent.ThreadPoolExecutor 
| 615 | run  in java.util.concurrent.ThreadPoolExecutor$Worker 
^ 722 | run . . . in java.lang.Thread 
+0

возможно дубликат [структуру дерева в Горме (Грааль)] (http://stackoverflow.com/questions/5880672/tree-structure-in-gorm -grails) –

+0

@tim_yates Не каждый вопрос к той же теме является дубликатом! – confile

ответ

1

дерево обычно имеет один из родителей на узел. Вы можете определить узел дерева, имеющий отношение один-ко-многим в себе так:

class TreeNode { 
    TreeNode parent 
    static hasMany = [children: TreeNode] 
    static mappedBy = [children: 'parent'] 
} 

Если у него есть несколько родителей, это на самом деле не дерево в смысле информатики. Эта структура данных обычно называется ориентированным графом. Вы можете смоделировать его как отношение многих к многим, например:

class GraphNode { 
    static hasMany = [children: GraphNode] 
    static hasMany = [parents: GraphNode] 
    static mappedBy = [children: 'parents', parents: 'children'] 
} 
+0

Как вставлять и удалять узлы? Как расширить отношения с такими свойствами, как dateCreated? – confile

+0

Вставить и удалить, как и любой другой объект домена grails. В примере «GraphNode» вызовите 'node.addToParents (parent)' или 'node.addToChildren (child)', чтобы добавить родителя или ребенка перед сохранением. Если вам нужны свойства в самой связи, вам лучше моделировать отношения как отдельную сущность, например. 'GraphNode' и' GraphEdge'. – ataylor

+0

Я обновил свой пост. У вас есть идеи для этого? – confile

0

ataylor is right. Для описания отношений, вы должны использовать 2 класса домена:

class Node { 
    static hasMany = [relations: Relation] 
} 
class Relation { 
    Node fromNode 
    Node toNode 
    String name //ex. 'son' 
    String reverseName // ex. 'father' 
} 
+0

Я обновил свой пост. У вас есть идеи для этого? – confile

+0

Я думаю, вам нужно добавить 'static belongsTo = [parent: TreeNode]' –