Jooq是否具备QueryDSL式自动计数分页的便捷查询方法?
在jOOQ中实现自动分页+计数查询
jOOQ提供了简洁的方式实现类似QueryDSL的自动分页查询,无需手动拆分计数查询和数据查询,下面是具体实现方案:
方案1:使用fetchPage()方法(推荐)
jOOQ 3.12及以上版本提供了Page类型和ResultQuery.fetchPage()方法,能自动完成计数查询和数据查询,返回包含总条数和分页数据的Page对象。
优化后的示例代码:
var post = Tables.POST; var postChannel = Tables.POST_CHANNEL; var postTag = Tables.POST_TAG; // 构建完整的查询条件 Condition condition = noCondition(); if (StringUtils.hasText(title)) { condition = condition.and(post.TITLE.like("%" + title + "%")); } if (StringUtils.hasText(reference)) { condition = condition.and(post.REFERENCE.like("%" + reference + "%")); } if (enabled != null) { condition = condition.and(post.ENABLED.eq(enabled)); } if (publicly != null) { condition = condition.and(post.PUBLICLY.eq(publicly)); } if (createAtStart != null || createAtEnd != null) { condition = condition.and(post.CREATE_AT.between( createAtStart == null ? null : createAtStart.atStartOfDay(), createAtEnd == null ? null : createAtEnd.atTime(LocalTime.MAX) )); } if (channelId != null) { condition = condition.and(exists( selectOne().from(postChannel) .where(postChannel.POST_ID.eq(post.ID).and(postChannel.CHANNEL_ID.eq(channelId))) )); } if (tagId != null) { condition = condition.and(exists( selectOne().from(postTag) .where(postTag.POST_ID.eq(post.ID).and(postTag.TAG_ID.eq(tagId))) )); } // 构建分页查询 ResultQuery<Record> query = ctx.select(post.ID, post.VERSION, post.PREVIEW, post.REFERENCE, post.PATH, post.KEYWORDS, post.TITLE, post.CREATE_AT, post.ENABLED, post.PUBLICLY, post.TOC, post.POSTER) .from(post) .where(condition) .orderBy(post.CREATE_AT.desc()); // 自动执行计数查询+分页数据查询 Page<Record> pageResult = query.fetchPage(page.offset() / page.limit(), page.limit()); // 转换为自定义Paged对象 if (pageResult.total() == 0) { return Paged.empty(); } List<PostDTO> ret = pageResult.map(r -> r.into(PostDTO.class)); return Paged.of(pageResult.total().intValue(), ret);
方案2:手动复用查询对象获取计数
如果你需要更灵活的控制,也可以复用已构建的查询对象,通过fetchCount()获取总条数,再执行分页查询:
// 构建查询(同方案1) ResultQuery<Record> query = ctx.select(...) .from(post) .where(condition) .orderBy(post.CREATE_AT.desc()) .offset(page.offset()) .limit(page.limit()); // 获取总条数(自动忽略offset/limit/orderBy) long total = query.fetchCount(); if (total == 0) { return Paged.empty(); } // 获取分页数据 List<PostDTO> ret = query.fetch(r -> r.into(PostDTO.class)); return Paged.of((int) total, ret);
关键说明
fetchPage()方法会自动优化计数查询:它会移除原查询中的SELECT列、ORDER BY、OFFSET、LIMIT,只保留FROM和WHERE条件来执行计数,和QueryDSL的fetchResults()逻辑一致。- 修正了原代码中的两处变量错误:
reference条件误用title变量、publicly条件误用enabled变量。
内容的提问来源于stack exchange,提问作者KevinBlandy
相关产品推荐
相关产品推荐

