2011-05-04 8 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 (그리고 선택적으로 모든 하위 레벨)에 대한 참조가 있어야합니다. - Level에는 상위 레벨, 하위 레벨 및 전역 상위 트리에 대한 참조가 있어야합니다.

이와 같은 트리 구조를 얻으려면 올바른 방향을 제시해 주시겠습니까? 감사

+0

Hibernate는 재귀 적 구조를 좋아하지 않지만 가능하다. "하지만 많은 레벨과 하위 레벨이있는 ​​트리를로드 할 수 없을 때"라는 의미를 설명하십시오. 오류가 있습니까? –

+0

문제는 레벨이 상위 트리 ID로 채워지지만 트리를로드 할 때 레벨 클래스에 대해 "주어진 식별자가있는 둘 이상의 행을 찾았습니다."오류가 발생합니다. 귀하의 회신에 감사드립니다. – Wavyx

답변

-1

나는이 솔루션 (친구 덕분에) 결국 최대 절전 모드에 도움이되는 구성.

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가로드되는 것을 보장에 관해서는, 당신은 항상 각각 가져 오는 열망/비 지연 사용할 수를 생성 treeNode 부모와 자식 모두. 그러나 나무 구조가 매우 큰 경우 성능 저하가 발생할 수 있습니다 ...

eager/lazy fetching과 같습니다. 여기 좀보세요 : Using lazy property fetching in Grails/Gorm

+0

. 실제로 그러한 접근 방식을 사용하면 트리, 레벨 및 하위 레벨 간의 관계로 인한 혼란을 피할 수 있습니다. 하지만 당신이 말했듯이, 부모 트리에 대한 직접적인 언급은 없으며, 그것은 나에게 가장 좋은 시나리오는 아닙니다. – Wavyx

+0

부모 트리에 대한 직접적인 참조가 있지만 루트 트리가 아닌 경우에는 루트 트리가 아닙니다. 그러나 각 TreeNode 인스턴스에서 루트 트리를 가져올 수 있습니다. 또는 클래스 정의에'TreeNode rootNode'를 추가하여 루트 노드에 대한 명시 적 참조를 항상 추가 할 수 있습니다. 제 원래 징수가 왜 당신에게 가장 좋은 시나리오가 아닌지요? – netbrain

+1

또 다른 해결책은 설정하는 것입니다 는'TreeNode를 getRootNode는() { 문자열 HQL은 = 반환 TreeNode.execureQuery (HQL) "부모가 null의 TreeNode에서" }' – netbrain

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.

각 트리마다 하나 이상의 루트 노드가있는 것 같습니다. 이것은 특이한 접근법입니다. 작동 시키려면 엔터티 TreeLevel rootLevelSet<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 :

+0

그 이유는 내가 hasOne 및 hasMany 있습니다. 전체 구조를 연결하는 목적 : Tree의 rootLevel 및 모든 possible 하위 레벨에 대한 액세스, Level의 parentLevel에 대한 액세스 및 모든 레벨의 Tree에 대한 액세스. – Wavyx

+0

Hibernate 오류는 "엔티티 TREE에 LEVEL 유형의 여러 하위 항목이 있지만 Java 클래스의 필드는 단일 참조 일뿐입니다"를 의미합니다. 따라서 동일한 트리에 여러 개의 루트 노드를 추가해야합니다. –