2011-05-04 149 views
3

我想在GORM中定義一個樹結構。這裏是我的模型:GORM中的樹結構(grails)

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

插入似乎工作正常,但是當我無法加載一個具有許多級別和子級別的樹。 我想我錯過了關係中的某些東西: - 樹應該有一個對rootLevel的引用(並且可選地指向所有子元素) -a Level應該引用其父級別,其子級別和全局父樹

你能指出我得到一個像這樣的樹結構的正確方向嗎? 感謝

+0

Hibernate不喜歡遞歸結構,但它是可能的。請解釋一下你的意思,但是當我無法加載多層次,多層次的樹時。你有錯誤還是什麼? – 2011-05-04 08:36:17

+0

問題是級別填充了父級樹ID,但是當您加載樹時,Level級別出現以下錯誤「找到給定標識符的多行」。 – Wavyx 2011-05-04 09:25:27

回答

-1

我結束了這個解決方案(感謝朋友):

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配置來幫助休眠。

11

我不喜歡你的樹結構,所以我創建了自己:)

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

對於確保所有樹節點被裝載,就可以隨時使用急於/非延遲獲取每個treeNode父母和孩子。但是,如果你的樹結構非常大,可能會有性能損失...

至於渴望/懶惰抓取。看看這裏:Using lazy property fetching in Grails/Gorm

+0

感謝您的回覆。事實上,通過這種方法,您可以避免樹,層和子級之間的關係混亂。但正如你所說,沒有直接引用父樹,這對我來說不是最好的場景。 – Wavyx 2011-05-04 09:29:44

+0

有一個直接引用父樹,但不是根樹,如果這就是你所要做的。但是,可以從每個TreeNode實例獲取根樹。或者,您可以通過將「TreeNode rootNode」添加到類定義來始終添加對根節點的顯式引用。任何原因,爲什麼我原來的porposal不是你最好的場景? – netbrain 2011-05-04 09:35:35

+1

另一個解決方案是設置 '樹節點getRootNode(){ 字符串HQL =「從樹節點,其中親本是空」 返回TreeNode.execureQuery(HQL) }' – netbrain 2011-05-04 09:37:50

0

The problem is that levels are filled with the parent Tree id, but when you load the Tree, you have the following error "More than one row with the given identifier was found" for the Level class.

你的問題似乎是,你有多個單一的根節點爲每棵樹。這是一種不尋常的方法。要使其正常工作,您必須將實體Tree中的Level rootLevel替換爲Set<Level> roots

+0

這就是爲什麼我有兩個hasOne和hasMany。它具有完全鏈接結構的目的:訪問樹中的rootLevel和所有可能的子層,從Level訪問parentLevel和從任何層訪問樹。 – Wavyx 2011-05-04 09:46:43

+0

Hibernate錯誤的意思是「實體TREE有幾個類型爲LEVEL的孩子,但Java類中的字段只是一個單一的引用」。所以你必須添加幾個根節點到同一棵樹上。 – 2011-05-06 10:24:24