Vì đây là một câu hỏi rất phổ biến, tôi đã viết
bài viết này , trên đó câu trả lời này dựa trên.
Các setFirstResult
và setMaxResults
Query
phương pháp
Đối với JPA và Hibernate Query
, setFirstResult
phương thức này tương đương OFFSET
và setMaxResults
phương thức này tương đương với GIỚI HẠN:
List<Post> posts = entityManager
.createQuery(
"select p " +
"from Post p " +
"order by p.createdOn ")
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
Sự LimitHandler
trừu tượng
Hibernate LimitHandler
định nghĩa logic phân trang cụ thể cho cơ sở dữ liệu và như được minh họa bằng sơ đồ sau, Hibernate hỗ trợ nhiều tùy chọn phân trang cụ thể cho cơ sở dữ liệu:
Bây giờ, tùy thuộc vào hệ thống cơ sở dữ liệu quan hệ cơ bản mà bạn đang sử dụng, truy vấn JPQL ở trên sẽ sử dụng cú pháp phân trang thích hợp.
MySQL
SELECT p.id AS id1_0_,
p.created_on AS created_2_0_,
p.title AS title3_0_
FROM post p
ORDER BY p.created_on
LIMIT ?, ?
PostgreSQL
SELECT p.id AS id1_0_,
p.created_on AS created_2_0_,
p.title AS title3_0_
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?
Máy chủ SQL
SELECT p.id AS id1_0_,
p.created_on AS created_on2_0_,
p.title AS title3_0_
FROM post p
ORDER BY p.created_on
OFFSET ? ROWS
FETCH NEXT ? ROWS ONLY
Oracle
SELECT *
FROM (
SELECT
row_.*, rownum rownum_
FROM (
SELECT
p.id AS id1_0_,
p.created_on AS created_on2_0_,
p.title AS title3_0_
FROM post p
ORDER BY p.created_on
) row_
WHERE rownum <= ?
)
WHERE rownum_ > ?
Ưu điểm của việc sử dụng setFirstResult
và setMaxResults
là Hibernate có thể tạo cú pháp phân trang cụ thể cho cơ sở dữ liệu cho bất kỳ cơ sở dữ liệu quan hệ được hỗ trợ nào.
Và, bạn không bị giới hạn chỉ với các truy vấn JPQL. Bạn có thể sử dụng setFirstResult
và setMaxResults
phương thức bảy cho các truy vấn SQL gốc.
Các truy vấn SQL gốc
Bạn không phải mã hóa phân trang cụ thể cho cơ sở dữ liệu khi sử dụng các truy vấn SQL gốc. Hibernate có thể thêm nó vào truy vấn của bạn.
Vì vậy, nếu bạn đang thực hiện truy vấn SQL này trên PostgreSQL:
List<Tuple> posts = entityManager
.createNativeQuery(
"SELECT " +
" p.id AS id, " +
" p.title AS title " +
"from post p " +
"ORDER BY p.created_on", Tuple.class)
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
Hibernate sẽ biến đổi nó như sau:
SELECT p.id AS id,
p.title AS title
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?
Thật tuyệt phải không?
Ngoài phân trang dựa trên SQL
Phân trang là tốt khi bạn có thể lập chỉ mục các tiêu chí lọc và sắp xếp. Nếu các yêu cầu phân trang của bạn ngụ ý lọc động, thì đó là cách tiếp cận tốt hơn nhiều để sử dụng giải pháp đảo ngược chỉ mục, như ElasticSearch.
Kiểm tra bài viết này để biết thêm chi tiết.
Hibernate-5.0.12
. Điều này vẫn không có sẵn? Sẽ rất nặng nề để có được một triệu bản ghi hoặc sau đó áp dụng bộ lọc trên đó -setMaxResults
thông qua @Rachel trong câu trả lời của @skaffman.