2011-10-25 66 views
9

是否有任何方法來限制JPA中@OneToMany關係的列表大小? 這是我的代碼示例:@OneToMany映射列表大小限制

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST) 
private List<Comment> commentList; 

我正在使用EclipseLink 2.3 JPA實現。 在此先感謝。在Bean驗證規範(JSR-303)的

+0

[在JPA中使用批註可以使用where子句限制子記錄嗎?](http://stackoverflow.com/questions/5857936/using-annotations-in-jpa-can-i-limit-child -records-with-a-where-clause) –

+0

這篇文章想要限制有多少元素被保存,而鏈接的人想要檢索也有其他一些條件的元素。因此不是「完全重複」。 – DataNucleus

回答

12

一部分是@Size(min=, max=)註釋:

支持的類型包括字符串,收集,地圖和數組。檢查註釋的元素大小是否在最小值和最大值之間(包括)。

您可以驗證集合。

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST) 
@Size(min=1, max=10) 
private List<Comment> commentList; 
2

你不能在JPA中做到這一點,因爲映射是爲了反映關係中有多少對象的現實而設計的。

你是否因爲性能而這樣做?如果是這樣,你可以做的是使用懶惰取的風格和使用BATCHSIZE標註具體的你要多少獲取一次:

* 修正:@Batchsize是一個休眠功能

@OneToMany(mappedBy = "publication", cascade=CascadeType.PERSIST, fetch=LAZY) 
@BatchSize(size=16) 
private List<Comment> commentList; 

然後在你的代碼中,只需迭代/循環到你想要的映射集合中。無論哪種方式,從我的經驗來看,「黑客」映射去做Criterias/Querys所設計的是不是一個有成效的努力,當你需要比@OneToMany明確提供的更多控制或性能調優時,最好的方法可能是隻是做一個查詢。

+0

應該澄清你的意思是「限制」,我的答案涉及模仿SQL LIMIT。如果您想對尺寸進行驗證,請使用@jeha回答的尺寸標註。 –

+0

這是從休眠批處理? – pringlesinn

+0

可能,我使用這兩個,所以我可能會讓他們混淆起來。 :( –

0

沒有真正的ortodox這樣做的方式。 我會讓關係懶,查詢父對象。在病房不初始化惰性列表後,並根據第一個查詢運行另一個查詢,該查詢運行在子表上。通過這種方式,您可以將結果集限制在主要條件中,而不是在連接條件上。或者,您可以只運行第二個查詢(僅在子表上),並帶有分頁支持。

2

真正的問題是收集本身。您應該而不是這種方式模擬您的業務領域。這種解決方案(集合註解@OneToMany)只適用於小集合(幾十個對象),而不適用於大集合(成千上萬的對象),這可能是評論的情況。你必須小心他們,因爲他們很快就會失去控制。我目前僅使用它們來模擬與Account相關聯的Role的集合,因爲我知道沒有帳戶在我的域中擁有超過9個角色,並且因爲帳戶所處的角色對於工作非常重要與帳戶。對於所有其他m-to-n關係,我使用普通的舊查詢。

與其向您的對象添加註釋集合,請明確添加對該對象的引用Comment明確使用查詢獲取您想要的註釋。

定義上Comment命名查詢來獲取某個對象的意見(讓我們用Article):

@Entity 
@NamedQueries(value={ 
    @NamedQuery(name=Comment.FOR_ARTICLE, query= 
     "SELECT c FROM Comment c WHERE c.article = :article" 
    ) 
}) 
public class Comment { 
    // ... 
    @ManyToOne 
    @JoinColumn(name = "articleId") 
    private Article article; 
} 

然後,使用一個名爲查詢i.c.w. Query.setMaxResultsQuery.setFirstResult明確地控制多少結果獲得並允許分頁等:

@PersistenceContext 
EntityManager em; 

Article theArticle = ...; 

Query query = em.createNamedQuery(Comment.FOR_ARTICLE, Comment.class); 
query.setParameter("article", theArticle); 
query.setFirstResult(0); 
query.setMaxResults(10); 
List<Comment> comments = (List<Comment>) query.getResultList(); 

要做到分頁,只是setFirstResult與 相應要顯示的頁面的第一個結果。例如。要顯示結果20 .. 29,您可以撥打 setFirstResult(20)