Mar*_*Joo 7 java orm pagination hibernate jpa
我试图使用Hibernate分页查询(PostgreSQL)
我为我的sql查询设置了setFirstResult(0),setMaxResults(20).我的代码如下:
Session session = getSessionFactory().getCurrentSession();
session.beginTransaction();
Query query = session.createQuery("FROM Customers");
query.setFirstResult(0);
query.setMaxResults(20);
List<T> entities = query.list();
session.getTransaction().commit();
Run Code Online (Sandbox Code Playgroud)
但是在查看SQL hibernate日志时,我仍然看到完整的SQL查询:
Hibernate: select customer0_.id as id9_, customer0_.customer_name as dst2_9_, customer0_.addres as dst3_9_ from tbl_customers customer0_
Run Code Online (Sandbox Code Playgroud)
为什么查询Hibernate分页SQL日志时没有LIMIT OFFSET?
有谁知道Hibernate分页机制?
我猜Hibernate将选择所有数据,将数据放入Resultset,然后在Resultset中进行分页,对吧?
我在查询和休眠回叫中使用。两者都按预期工作。Hibernate Query执行的结果介于给定的First和Max大小之间。在这里,好像您传递了SQL而不是HQL进行查询。如果是的话,那应该行不通。
-在这里查看我的代码。
Query query = this.getSession().createQuery("FROM QueryType");
query.setFirstResult(0);
query.setMaxResults(20);
List toDelete = query.list();
Run Code Online (Sandbox Code Playgroud)
并在日志中:
select * from(从MY_TBL_NAME querytype0_选择(选择-所有列名称。(不想在此处共享。))rownum <=?
有很多方法可以分页.
HQL和setFirstResult,setMaxResults API
Session session = sessionFactory.openSession();
Query query = session.createQuery("From Foo");
query.setFirstResult(0);
query.setMaxResults(10);
List<Foo> fooList = query.list();
//Total count
String countQ = "Select count (f.id) from Foo f";
Query countQuery = session.createQuery(countQ);
Long countResults = (Long) countQuery.uniqueResult();
//Last Page
int pageSize = 10;
int lastPageNumber = (int) ((countResult / pageSize) + 1);
Run Code Online (Sandbox Code Playgroud)
HQL和ScrollableResults API
String hql = "FROM Foo f order by f.name";
Query query = session.createQuery(hql);
int pageSize = 10;
ScrollableResults resultScroll = query.scroll(ScrollMode.FORWARD_ONLY);
resultScroll.first();
resultScroll.scroll(0);
List<Foo> fooPage = Lists.newArrayList();
int i = 0;
while (pageSize > i++) {
fooPage.add((Foo) resultScroll.get(0));
if (!resultScroll.next())
break;
}
//Total count
resultScroll.last();
int totalResults = resultScroll.getRowNumber() + 1;
Run Code Online (Sandbox Code Playgroud)
只需Criteria API
Criteria criteria = session.createCriteria(Foo.class);
criteria.setFirstResult(0);
criteria.setMaxResults(pageSize);
List<Foo> firstPage = criteria.list();
//Total count
Criteria criteriaCount = session.createCriteria(Foo.class);
criteriaCount.setProjection(Projections.rowCount());
Long count = (Long) criteriaCount.uniqueResult();
Run Code Online (Sandbox Code Playgroud)
baeldung用例子列出了所有这些.
您可以将 JPA 分页用于实体查询和本机 SQL。
为了限制底层查询的ResultSet
大小,JPAQuery
接口提供了setMaxResults
方法.
导航下一页需要将结果集定位在上一页结束的位置。为此,JPAQuery
接口提供了setFirstResult
方法。
List<Post> posts = entityManager.createQuery("""
select p
from Post p
order by p.createdOn
""", Post.class)
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
Run Code Online (Sandbox Code Playgroud)
JPA 查询分页不限于仅返回实体的实体查询。您也可以将它用于 DTO 投影。
List<PostCommentSummary> summaries = entityManager.createQuery("""
select new
com.vladmihalcea.book.hpjp.hibernate.fetching.PostCommentSummary(
p.id, p.title, c.review
)
from PostComment c
join c.post p
order by c.createdOn
""")
.setMaxResults(10)
.getResultList();
Run Code Online (Sandbox Code Playgroud)
JPA 查询分页不限于实体查询,例如 JPQL 或 Criteria API。您也可以将它用于本机 SQL 查询。
List<Post> posts = entityManager.createQuery("""
select p
from Post p
left join fetch p.comments
where p.title like :titlePattern
order by p.createdOn
""", Post.class)
.setParameter("titlePattern", "High-Performance Java Persistence %")
.setMaxResults(5)
.getResultList();
Run Code Online (Sandbox Code Playgroud)
但是,如果我们尝试JOIN FETCH
在实体查询中使用子句,同时也使用 JPA 分页:
List<Post> posts = entityManager.createQuery("""
select p
from Post p
left join fetch p.comments
where p.title like :titlePattern
order by p.createdOn
""", Post.class)
.setParameter("titlePattern", "High-Performance Java Persistence %")
.setMaxResults(5)
.getResultList();
Run Code Online (Sandbox Code Playgroud)
Hibernate 将发出以下警告消息:
HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!
Run Code Online (Sandbox Code Playgroud)
并且执行的 SQL 查询将缺少分页子句:
SELECT p.id AS id1_0_0_,
c.id AS id1_1_1_,
p.created_on AS created_2_0_0_,
p.title AS title3_0_0_,
c.created_on AS created_2_1_1_,
c.post_id AS post_id4_1_1_,
c.review AS review3_1_1_,
c.post_id AS post_id4_1_0__,
c.id AS id1_1_0__
FROM post p
LEFT OUTER JOIN post_comment c ON p.id=c.post_id
WHERE p.title LIKE :titlePattern
ORDER BY p.created_on
Run Code Online (Sandbox Code Playgroud)
这是因为 Hibernate 想要按照JOIN FETCH
子句的指示完全获取实体及其集合,而 SQL 级别的分页可能会截断ResultSet
可能留下集合中Post
元素较少的父实体comments
。
HHH000104
警告的问题在于 Hibernate 将获取Post
和PostComment
实体的乘积,并且由于结果集的大小,查询响应时间将很重要。
为了解决此限制,您必须使用窗口函数查询:
@NamedNativeQuery(
name = "PostWithCommentByRank",
query = """
SELECT *
FROM (
SELECT
*,
DENSE_RANK() OVER (
ORDER BY "p.created_on", "p.id"
) rank
FROM (
SELECT
p.id AS "p.id", p.created_on AS "p.created_on",
p.title AS "p.title", pc.post_id AS "pc.post_id",
pc.id as "pc.id", pc.created_on AS "pc.created_on",
pc.review AS "pc.review"
FROM post p
LEFT JOIN post_comment pc ON p.id = pc.post_id
WHERE p.title LIKE :titlePattern
ORDER BY p.created_on
) p_pc
) p_pc_r
WHERE p_pc_r.rank <= :rank
""",
resultSetMapping = "PostWithCommentByRankMapping"
)
@SqlResultSetMapping(
name = "PostWithCommentByRankMapping",
entities = {
@EntityResult(
entityClass = Post.class,
fields = {
@FieldResult(name = "id", column = "p.id"),
@FieldResult(name = "createdOn", column = "p.created_on"),
@FieldResult(name = "title", column = "p.title"),
}
),
@EntityResult(
entityClass = PostComment.class,
fields = {
@FieldResult(name = "id", column = "pc.id"),
@FieldResult(name = "createdOn", column = "pc.created_on"),
@FieldResult(name = "review", column = "pc.review"),
@FieldResult(name = "post", column = "pc.post_id"),
}
)
}
)
Run Code Online (Sandbox Code Playgroud)
有关使用窗口函数解决
HHH000104
问题的更多详细信息以及DistinctPostResultTransformer
.
归档时间: |
|
查看次数: |
25409 次 |
最近记录: |