2011-10-25 50 views
9

Có cách nào để giới hạn kích thước của danh sách mối quan hệ @OneToMany trong JPA không? Đây là mẫu mã của tôi:@OneToMany giới hạn kích thước danh sách ánh xạ

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

Tôi đang sử dụng EclipseLink 2.3 JPA implementation. Cảm ơn trước.

+0

có thể trùng lặp của [Sử dụng chú thích trong JPA tôi có thể giới hạn bản ghi con với mệnh đề where?] (Http://stackoverflow.com/questions/5857936/using-annotations-in-jpa-can-i-limit-child -records-with-a-where-clause) –

+0

Bài đăng này muốn hạn chế số lượng phần tử được duy trì, trong khi bài đăng được liên kết muốn truy xuất các phần tử cũng có một số tiêu chí khác. Do đó không phải là "trùng lặp chính xác". – DataNucleus

Trả lời

12

Một phần của Bean Validation Đặc điểm kỹ thuật (JSR-303) là @Size(min=, max=) chú thích:

loại được hỗ trợ là String, Bộ sưu tập, Bản đồ và mảng. Kiểm tra xem kích thước phần tử có chú thích nằm trong khoảng giữa min và max (bao gồm) hay không.

Bạn có thể xác thực bộ sưu tập.

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

Bạn không thể làm điều này trong JPA và nó không có ý nghĩa vì ánh xạ được thiết kế để phản ánh thực tế có bao nhiêu đối tượng đang ở trong mối quan hệ.

Bạn có thực hiện điều này vì hiệu suất không? Nếu có điều gì bạn có thể làm là sử dụng một Lazy lấy phong cách và sử dụng Batchsize chú thích để cụ thể có bao nhiêu bạn muốn lấy một lần:

* chỉnh: @Batchsize là một tính năng Hibernate

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

Sau đó, trong mã của bạn, chỉ cần lặp/vòng lặp đến nơi bạn muốn trong bộ sưu tập được ánh xạ này. Dù bằng cách nào, từ kinh nghiệm của tôi "hacking" ánh xạ để làm những gì Criterias/Querys được thiết kế cho không phải là một nỗ lực hiệu quả, khi bạn cần kiểm soát nhiều hơn hoặc hiệu suất điều chỉnh hơn @OneToMany cung cấp một cách rõ ràng, cách tốt nhất có thể để thực hiện một truy vấn.

+0

Nên làm rõ về ý nghĩa của bạn bằng "giới hạn", câu trả lời của tôi đề cập đến việc bắt chước các GIỚI HẠN SQL. Thay vào đó, nếu bạn muốn xác thực kích thước, hãy sử dụng chú thích Kích thước như được trả lời bởi @jeha. –

+0

Đây có phải là Batchsize từ Hibernate không? – pringlesinn

+0

Có thể, tôi sử dụng cả hai vì vậy tôi có thể đã có chúng hỗn hợp. :( –

0

Không có cách nào khác để thực hiện điều này. Tôi sẽ làm cho mối quan hệ lười biếng, truy vấn cho các đối tượng cha mẹ. Sau khi các phường không khởi tạo danh sách lười biếng và chạy truy vấn khác dựa trên truy vấn đầu tiên, chạy trên bảng con. Bằng cách này, bạn có thể giới hạn tập hợp kết quả theo các tiêu chí chính chứ không giới hạn tiêu chí tham gia. Hoặc bạn chỉ có thể chạy truy vấn thứ hai (chỉ trên bảng con), với sự hỗ trợ phân trang.

2

Vấn đề thực sự là chính bộ sưu tập. Bạn nên không phải mô hình miền doanh nghiệp của mình theo cách này. Giải pháp này (của các bộ sưu tập chú thích với @OneToMany) chỉ khả thi đối với các bộ sưu tập nhỏ (hàng chục đối tượng) và không cho các bộ sưu tập lớn (hàng nghìn đối tượng) có thể là trường hợp có nhận xét. Bạn thực sự phải xem với họ khi họ có thể nhanh chóng phát triển ngoài tầm kiểm soát. Hiện tại, tôi đang sử dụng chúng để mô hình hóa bộ sưu tập của Role được liên kết với một số Account, bởi vì tôi biết rằng sẽ không có tài khoản nào có hơn 9 vai trò trong miền của tôi và vì vai trò của tài khoản là rất quan trọng để làm việc với tài khoản. Đối với tất cả các quan hệ m-to-n khác, tôi đang sử dụng các truy vấn cũ đơn giản.

Thay vì thêm bộ sưu tập nhận xét vào đối tượng của bạn, hãy thêm tham chiếu đến đối tượng trên Commentrõ ràng nhận các nhận xét bạn muốn bằng truy vấn.

Xác định một truy vấn có tên trên Comment để có được những cảm nhận cho một đối tượng nào đó (chúng ta hãy sử dụng 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; 
} 

Sau đó, sử dụng mà tên i.c.w. truy vấn Query.setMaxResultsQuery.setFirstResult để dứt khoát kiểm soát có bao nhiêu kết quả để có được và cho phép phân trang vv:

@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(); 

Để làm phân trang, chỉ cần setFirstResult đến kết quả đầu tiên tương ứng với trang web mà bạn muốn hiển thị. VÍ DỤ. để hiển thị kết quả 20 .. 29, bạn sẽ gọi setFirstResult(20).

Các vấn đề liên quan