2012-03-20 101 views
0

我有一個目錄類型結構表示爲實體,即認爲目錄實體和文件實體。Hibernate遞歸獲取連接不遞歸獲取所有的孩子

該目錄實體具有一個文件實體和一個目錄實體集合的集合。

我想獲取根目錄和'預加載'所有目錄和那裏的文件。

我想:

String queryString = "SELECT DISTINCT d FROM " + 
    Directory.class.getSimpleName() + 
    " d LEFT JOIN FETCH d.files LEFT JOIN FETCH d.directories child LEFT JOIN FETCH child.files LEFT JOIN FETCH child.directories WHERE f.root = :isRoot); 
Query query = em.createQuery(queryString); 
query.setParameter("isRoot", true); 

Directory dir = (Directory) query.getSingleResult(); 

的查詢工作,它只是不會預先加載的一切。我得到所有的根目錄和根文件,但是當我開始進入子目錄並獲取文件查詢時。 I.E.這似乎是遞歸不起作用。

我也嘗試只是一個連接抓取(我認爲這確實內部聯接提取),沒有運氣。

任何想法?

+0

它肯定不會!如果您閱讀了文檔,則指出:通常,獲取連接通常不需要分配別名,因爲不應在where子句(或任何其他子句)中使用關聯的對象。關聯的對象也不會直接返回到查詢結果中。相反,它們可以通過父對象訪問。你可能需要一個別名的唯一原因是,如果你遞歸連接抓取進一步收集:從貓 如貓 內連接抓取cat.mate 左加入取cat.kittens孩子 LEFT JOIN因此,如果取child.kittens – lostintranslation 2012-03-20 19:01:58

+0

你在那篇文章中讀到了更多這是我正在尋找的:'雖然不可能寫出你所要求的遞歸查詢,但是可以用HQL熱切地獲取層次結構;這樣做至少可以讓你在內存中遍歷樹,而不必爲每個級別敲擊數據庫。 select n from node n left join fetch n.Children' – lostintranslation 2012-03-20 19:04:52

+0

I stand corrected =) – esaj 2012-03-20 19:20:22

回答

2

我面臨着同樣的問題,但在我的情況下,單個表存儲多個獨立的樹。因此,「從n節點中選擇n從左連接獲取n.Children」將會把所有的樹提取到內存中,而我需要單個樹。添加一個WHERE子句會破壞遞歸。

所以我用一個遞歸幫助我的DAO裏面:

private Node fetchChildren(Node parent) { 
    Hibernate.initialize(parent.getChildren()); 
    for (Node child : parent.getChildren()) { 
     fetchChildren(child); 
    } 
    return parent; 
} 
0

您是否已將實體之間的提取定義爲渴望(@OneToMany(fetch = FetchType.EAGER))?

現在看來,這可以解決在初始取問題爲您的問題(more detailed answer)。

esaj comment link answer包含處理遞歸的方式。

希望這有助於

+1

謝謝,但那不是我想要的。原因是我想默認行爲是懶惰的,只有重寫該行爲的查詢應該遞歸地提取獲取。 Hibernate文檔說他們支持這種類型的行爲。 – lostintranslation 2012-03-20 18:59:54