2010-10-19 39 views
14

Giả sử tôi có một thực thể Bưu chính, một thực thể luận và một đến nhiều mối quan hệ:Làm thế nào tôi có thể làm phân trang với bộ sưu tập @OneToMany

@Entity class Post { 
    ... 
    @OneToMany 
    List<Comment> comments; 
    ... 
} 

Làm thế nào tôi có thể đạt được phân trang như thế này:

Post post = //Find the post. 
return post.getComments().fetch(100, 10); // Find the 11th page (page size 10); 

Có thể mô phỏng phân trang động với bộ sưu tập @OneToMany trên JPA, hoặc chúng ta phải viết lại cơ chế liên kết của JPA hoàn toàn không? (ví dụ: tạo một loại bộ sưu tập PersistentList có thể quản lý phân trang, sắp xếp và tìm kiếm).

P.S .: Gần đây tôi đã tìm thấy Play! khuôn khổ sử dụng một lib rất thú vị trên đầu trang của JPA: Siena. Siena là rất dễ sử dụng, và là một trừu tượng tốt trên đầu trang của JPA/Hibernate. Nhưng tôi không thể tìm cách phân trang với các hiệp hội của nó.

Cập nhật:

Chơi khuôn khổ có một cú pháp truy vấn tương tự như Django:

Post.findAll().from(100).fetch(10); // paging 

nơi

Post.findAll() 

sẽ trả về một đối tượng JPAQuery, một loại truy vấn tùy chỉnh trong Play.

Nhưng với bộ sưu tập liên quan, ví dụ .:

Post.comments 

sẽ chỉ trả lại một danh sách, mà không hỗ trợ phân trang hoặc truy vấn khác.

tôi đã tự hỏi làm thế nào để mở rộng nó, do đó

Post.comments 

cũng sẽ trả về một đối tượng JPAQuery hoặc tương tự, sau đó bạn có thể truy vấn trên "truy vấn" bộ sưu tập:

Post.comments.from(100).fetch(10); 

hoặc chèn Nhận xét mới mà không thực sự tìm nạp bất kỳ nhận xét nào:

Post.comments.add(new Comment(...)); 

Theo suy nghĩ đầu tiên của tôi, chúng tôi có thể tạo một lớp con của Danh sách, sau đó lớp Bài đăng sẽ trở thành:

@Entity class Post { 
    ... 
    @OneToMany 
    QueryList<Comment> comments; 
    ... 
} 

và QueryList sẽ có các phương thức fetch(), from() gián tiếp tới JPAQuery's.

Nhưng tôi không biết liệu Hibernate/JPA có nhận ra điều này hay can thiệp vào nó hay không.

Trả lời

7

Có thể bắt chước phân trang năng động với bộ sưu tập @OneToMany trên đầu trang của JPA (...)

Không được hỗ trợ. Cách tiếp cận tiêu chuẩn sẽ là sử dụng truy vấn JPQL để truy xuất các nhận xét cho một bài đăng nhất định và và sử dụng Query#setFirstResult(int)Query#setMaxResults(int).

Theo suy nghĩ đầu tiên của tôi, chúng tôi có thể tạo một lớp con của Danh sách, (...).Nhưng tôi không biết liệu Hibernate/JPA có nhận ra điều này hay can thiệp vào nó hay không.

Rõ ràng là không có bản vá nặng để thay đổi đáng kể hành vi mặc định.

+0

BTW. Tôi thấy rằng Hibernate sẽ "chặn" Bộ sưu tập @OneToMany, và gián tiếp nó vào một truy vấn. Vì vậy, có thể "cắm" hệ thống Hibernate với một loại bộ sưu tập tùy chỉnh (ví dụ: @OneToMany LazyQueryList, có phương thức tìm nạp (bắt đầu, bù đắp)) mà Hibernate sẽ nhận ra? –

+1

@Visus Có thể ** vá ** Hibernate, rất khác với cơ chế plugin, và đây không phải là một bản vá nhỏ. Chúc may mắn nếu bạn quyết định đi theo hướng này. –

+0

Cảm ơn bạn đã làm rõ. Tôi mới với hibernate, và một bản vá nặng chắc chắn là ngoài khả năng của tôi. Nhưng tôi vẫn bị mắc kẹt với cách sử dụng các hiệp hội một cách hiệu quả. Tôi thấy bạn nói về các dự án sử dụng hibernate một cách tồi tệ - 'không sử dụng các hiệp hội bởi vì họ sợ "tìm nạp toàn bộ cơ sở dữ liệu", trong một câu trả lời cho một câu hỏi khác. Tôi thực sự muốn biết làm thế nào không để lấy một bộ sưu tập toàn bộ. Hoặc, trong trường hợp tạo các truy vấn JPQL theo cách thủ công cho bộ sưu tập, điều đó có nghĩa là chúng tôi chỉ sử dụng bộ sưu tập liên kết cho ánh xạ? Làm thế nào chúng ta có thể đặt chúng trở lại Post.com? –

3

Tôi nghĩ rằng "đúng" cách có thể như hơn:

@Entity 
class Post { 
    ... 

    public GenericModel.JPAQuery getComments() { 
     return Comment.find("post_id = ?", post_id); 
    } 
} 

và sau đó sử dụng một trong những fetchmethods trong JPAQuery:

// fetch first page of results, 25 results per page 
post.getComments().fetch(1,25); 
Các vấn đề liên quan