You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

分页开发:Hibernate获取总行数、结果提取及分页参数设置问题

解决Hibernate分页中获取总记录数的问题

你现在的思路是对的——分页前需要先拿到总记录数来计算总页数,但你的写法有两个问题:一是带LEFT JOIN FETCH的查询直接用count(*)会因为关联表的重复记录导致计数不准;二是把count和实体放在同一个查询里返回,不仅效率低,还会得到重复的count值,处理起来也麻烦。

下面给你两种解决方案,推荐第一种(更高效、准确):

方案一:分两个查询(推荐)

分别查询总记录数和分页数据,这样既保证计数准确,也能保留分页参数的设置:

1. 查询总记录数

注意要用count(distinct pm.id)来避免关联表带来的重复计数(因为LEFT JOIN FETCH pm.computer会导致一个FriendComputer对应多个computer时,查询结果会重复出现该FriendComputer,直接用count(*)会把这些重复项也算进去):

// 构建总记录数查询
String countQuery = "SELECT count(distinct pm.id) FROM FriendComputer pm LEFT JOIN pm.computer m WHERE pm.friendAccount.id = :friendId";
Long totalRecords = session().createQuery(countQuery, Long.class)
                            .setParameter("friendId", friendId)
                            .getSingleResult();

2. 分页查询数据

保留你原来的查询逻辑,正常设置firstResult和maxResults即可:

// 构建分页数据查询
String dataQuery = "SELECT pm FROM FriendComputer pm LEFT JOIN FETCH pm.computer m WHERE pm.friendAccount.id = :friendId";
List<FriendComputer> pageData = session().createQuery(dataQuery, FriendComputer.class)
                                        .setParameter("friendId", friendId)
                                        .setFirstResult(0) // 可以根据页码动态计算:(pageNum - 1) * pageSize
                                        .setMaxResults(25)
                                        .getResultList();

方案二:处理单个查询返回的Object[](不推荐)

如果一定要把count和实体放在同一个查询里(不建议,因为会加载所有匹配的实体数据,浪费性能),你可以这样提取结果:

String queryString = "SELECT count(distinct pm.id), pm FROM FriendComputer pm LEFT JOIN FETCH pm.computer m WHERE pm.friendAccount.id = :friendId ";
org.hibernate.query.Query q = session().createQuery(queryString).setParameter("friendId", friendId);
// 这里如果设置maxResults,只会返回指定数量的结果,但count是总记录数
q.setMaxResults(25);

List<Object[]> results = q.getResultList();
if (!results.isEmpty()) {
    Object[] firstResult = results.get(0);
    Long totalCount = (Long) firstResult[0]; // 提取总记录数
    FriendComputer firstItem = (FriendComputer) firstResult[1]; // 提取第一个实体
    // 剩下的results里的元素也都是[count, FriendComputer]的结构,count值都是一样的
}

但再次强调:这种方式不仅效率低,而且如果不用distinct,count值会是重复后的记录数,不是实际的FriendComputer总数,所以非常不推荐。


内容的提问来源于stack exchange,提问作者Coder95

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:55:31