Java 休眠分页机制

Java 休眠分页机制,java,hibernate,jpa,orm,pagination,Java,Hibernate,Jpa,Orm,Pagination,我正在尝试对我的查询PostgreSQL使用Hibernate分页 我为SQL查询设置了setFirstResult0和setMaxResults20。我的代码如下: Session session = getSessionFactory().getCurrentSession(); session.beginTransaction(); Query query = session.createQuery("FROM Customers"); query.setFirstResult(0); q

我正在尝试对我的查询PostgreSQL使用Hibernate分页

我为SQL查询设置了setFirstResult0和setMaxResults20。我的代码如下:

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();
为什么Hibernate分页SQL日志查询中没有限制偏移量

有人知道Hibernate分页机制吗


我猜Hibernate将选择所有数据,将数据放入Resultset,然后在Resultset中分页,对吗?

我在查询和Hibernate回调中使用。这两项工作都如预期的那样。执行Hibernate查询的结果介于给定的第一个大小和最大大小之间。这里似乎是将SQL而不是HQL传递给查询。如果是的话,它不应该工作

-在这里查看我的代码

        Query query = this.getSession().createQuery("FROM QueryType");
        query.setFirstResult(0);
        query.setMaxResults(20);
        List toDelete = query.list();
在日志中:

挑选 * 从…起 选择 -所有列名。我不想在这里分享。 从…起 我的姓名查询类型0 哪里
rownum分页的方法很多

HQL和setFirstResult、setMaxResults API

HQL和ScrollableResults API

简单的标准API


列出了所有的实例。

您可以对实体查询和本机SQL使用JPA分页

为了限制基础查询结果集的大小,JPA查询接口提供了

导航下一页需要将结果集定位到上一页结束的位置。为此,JPA查询接口提供了

JPQL Hibernate将发出以下警告消息:

HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!
执行的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
这是因为Hibernate希望按照JOIN fetch子句的指示完整地获取实体及其集合,而SQL级别的分页可能会截断结果集,从而使父Post实体在comments集合中的元素更少

HH000104警告的问题是Hibernate将获取Post和Post命令实体的乘积,并且由于结果集的大小,查询响应时间将非常长

为了克服此限制,您必须使用查询:

有关使用窗口函数修复HH000104问题以及的代码的更多详细信息


不,Hibernate不这样做,它尝试在查询级别应用分页。我认为这是一个方言问题,你确定你在Hibernate配置中设置了Postgre方言吗?顺便问一下,这是SQL还是HQL?您必须将HQL传递给createQuery方法。在本例中,我使用的是:Hibernate查询示例HQLI使用的是Hibernate查询示例HQL我更新了代码,而不是本机SQL。它仍然显示所有日志查询。您使用ScrollableResults API的示例将所有内容读取到内存中。您可以按照@Sean S的解释使其工作。但它肯定不能提供一个简单的解决方案。依赖于RDBMS,并且不是所有RDBMS都有这个问题。很高兴知道,但这不是原始海报的问题/顾虑
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;
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();
List<Post> posts = entityManager.createQuery("""
    select p
    from Post p
    order by p.createdOn
    """, Post.class)
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
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();
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();
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();
HHH000104: firstResult/maxResults specified with collection fetch; applying in memory!
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
@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"),
            }
        )
    }
)