2014-03-12 59 views
2

假設我們有一個實體「Something」,並且這與某些「Data」具有一對多(數百萬)關係。使用JPA處理龐大的一對多集合的最佳方法

Something 1 -> * Data 
Data 1 -> 1 Something 

現在,如果我們想添加一些數據對象,我們應該這樣做:

Something.getDataList().add(Data) 

這實際上拉離數據庫中的所有數據對象是不是最佳恕我直言。

但是如果我移除內容的關係,並把它留在我的數據就可以添加和檢索這些人恰恰是我要求使用DAO對象:

Something 
Data 1 -> 1 Something 

現在數據訪問接口會看像這樣:

Something.addData(Data) // will use DataDAO to save object 

Something.addData(List<Data>) // will use same DataDAO batch insert 

我需要個一些指導是,也許我缺少JPA的一些知識,並且沒有必要這樣做?此外,我不確定實體是不是自然的這種方式,因爲數據是由他們的方法提供的,但實際上並沒有包含它(如果這是正確的話,我應該刪除每一個到多個關係,如果存在性能關鍵操作處理與那個特定的實體,這也是不自然的)。

在我的特殊情況下,我有很多定期更新數據庫的REST消費者。我使用的是ObjectDB,JPA ......但問題在這裏更加抽象。

+0

如果你想可以用一個很好的舊INSERT語句。 –

+1

並非如此:將原生SQL插入與JPA混合可能會導致很多問題,因爲EntityManager在執行刷新/合併之前不會知道新記錄,緩存將無效等。 – Cascader

+0

這就是爲什麼我不想使用SQL語句,但通過第二種方法,EntityManager被用於實現,因此它知道所有的事情......我對此有何看法?有人做過類似的事嗎? – vach

回答

2

我相信如果有DataSomething相關的數百萬個記錄,那麼使用something.getDataList()就是一個點擊炸彈。正如您所說,調用something.getDataList().add(data)將從數據庫中獲取整個數據集以執行單個插入。此外,任何人都可能試圖使用something.getDataList().size來獲取記錄的數量,導致相同的開銷。

我的建議是,你使用DataDAO這種行動(即添加或計數),如:

void addData(Something something, Data data){ 
    //Something similar can be used for batch insert 
    data.setSomething(something); 
    em.persist(data); 
} 

List<Data> findData(Something something, MyFilter filter){ 
    // use a NamedQuery with parameters populated by something and your filters 
    return em.getResultList(); 
} 

Long countData(Something something){ 
    // use a 'SELECT COUNT(*) FROM Data d WHERE d.something = :something' NamedQuery 
    return em.getSingleResult; 
} 
+0

所以你同意我的Something實體不應該有List 字段,而是數據應該有對「Something」的引用? – vach

+0

是的,這是正確的。 – Cascader