2011-02-25 221 views
2

Grrrrrr,試圖實現一個非常簡單的樹。它並不需要是雙向的(因爲遍歷只有自上而下),所以我想它會更好(即更節省空間),如果它是單向的,雖然我的映射失敗:樹與JPA [/休眠]

@Entity 
public class Node extends Model { 

    @Column(nullable=false, unique=true) 
    public String description; 

    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) 
    public List<Node> children = new LinkedList<Node>(); 

    public Node() {} 
    public Node(String description) { 
     this.description = description; 
    } 

    public void addChild(String description) { 

     Node child = new Node(description); 
     child.save(); 

     this.children.add(child); 
    } 
} 

通過「失敗」,我的意思是子關係沒有被映射,下面的單元測試失敗;最後的assert需要1,但得到0.在應用程序的CRUD部分,我可以看到兩個節點實際上都是創建並保存的,但父節點沒有任何子節點。由此我得出這樣的結論映射被打破:

public void testMenu() { 

    Node root = Node.find("byDescription", "root").first(); 
    if (root == null) { 
     root = new Node("root"); 
     root.save(); 
    } 

    assertNotNull(root); 

    root.addChild("child 1"); 

    JPA.em().flush(); 
    JPA.em().getTransaction().commit(); 
    JPA.em().getTransaction().begin(); 
    JPA.em().clear(); // clear cache to grab the root from the db 

    root = Node.find("byDescription", "root").first(); 
    assertEquals(1, root.children.size()); 

} 

我用玩!這就是爲什麼所有這些成員是公衆而不是私人的,爲什麼沒有getter/setter方法,爲什麼沒有一個Id字段(Id是從Model類繼承的)。這也是爲什麼那裏有一些非標準的功能,如find()save()。它們的功能非常直觀,訪問公共成員通過反射「轉換」爲調用提供或創建的setter和getter。

這並不重要,它是我的映射被打破,所以請嘗試專注於該問題,而不是側面問題,我相當肯定不會導致問題。

乾杯。

更新:

Hibernate的日誌:

Hibernate: /* from models.Node where description = ? */ select node0_.id as id35_, node0_.description as descript2_35_ from Node node0_ where node0_.description=? limit ? 
Hibernate: /* insert models.Node */ insert into Node (description) values (?) 
Hibernate: /* insert models.Node */ insert into Node (description) values (?) 
Hibernate: /* from models.Node where description = ? */ select node0_.id as id35_, node0_.description as descript2_35_ from Node node0_ where node0_.description=? limit ? 
Hibernate: /* load collection models.Node.children */ select children0_.Node_id as Node1_35_1_, children0_.children_id as children2_1_, node1_.id as id35_0_, node1_.description as descript2_35_0_ from Node_Node children0_ inner join Node node1_ on children0_.children_id=node1_.id where children0_.Node_id=? 

回答

1

如果粘貼休眠日誌這將有助於。

它不應該是絕對必要的,但你可以在root.addChild(「child 1」)後嘗試root.save()。

此外,您沒有提交事務,如果Node.find()使用相同的會話,那麼這不會成爲問題,但是這樣做?

+0

我試着重新排序所有的創建/保存/刷新/持續行動。沒有幫助。我現在將添加Hibernate日誌。 – davin 2011-02-25 13:23:23

+0

您是否嘗試在root.save()前加入孩子 – Pau 2011-02-25 13:39:16

+0

順便說一句,您使用的是哪個版本的JPA? JPA 1.0不支持onetomany單向 – Pau 2011-02-25 13:41:43