分页查询: select from purchase where id = #{id} and category = #{category} limit #{offset}, #{pageSize};
总页数查询:select count(1) from (select from purchase where id = #{id} and category = #{category}) t1;
PurchaseMapper mapper = sqlSession.getMapper(PurchaseMapper.class);
QueryCondition condition = new QueryCondition();
condition.setPageNum(pageNum);
condition.setPageSize(pageSize);
System.out.println(new PageVO<>(pageSize, pageNum, mapper.count(condition), mapper.findPageByHand(condition));
使用RowBounds
对象后,就不需要在SQL语句中写limit
语句了,但是仍然要对满足条件的数据条数进行单独查询,其结果将用于计算总页数。
PurchaseMapper mapper = sqlSession.getMapper(PurchaseMapper.class);
QueryCondition condition = new QueryCondition();
System.out.println(new PageVO<>(pageSize, pageNum, mapper.count(condition),
mapper.findAllPage(condition, new RowBounds((pageNum - 1)*pageSize, pageSize))));
RowBounds
分页是将所有的数据查询到内存中以后,再使用RowBounds
参数进行分页的(具体是通过游标),所以对内存的压力很大,性能很低,因此这种方式不建议使用。
使用拦截器拦截SQL语句的执行,并为SQL语句添加limit
关键字进行分页查询,以及count语句来查询总数
PurchaseMapper mapper = sqlSession.getMapper(PurchaseMapper.class);
QueryCondition condition = new QueryCondition();
Page page = pageHelper.startPage(pageNum, pageSize);
List<Purchase> purchaseList = mapper.findByCondition(condition);
System.out.println(new PageVO<>(pageSize, pageNum, (int)page.getTotal(), purchaseList));
原理:
对Executor
接口的query
方法进行了拦截。
在创建Executor
时,如果有插件对Executor
进行拦截,则会对Executor
对象生成代理,在执行相对应的方法时进行增强处理。
@Override
public Object intercept(Invocation invocation) throws Throwable {
try {
...
//调用方法判断是否需要进行分页,如果不需要,直接返回结果
if (!dialect.skip(ms, parameter, rowBounds)) {
//判断是否需要进行count查询
if (dialect.beforeCount(ms, parameter, rowBounds)) {
//查询总数
Long count = count(executor, ms, parameter, rowBounds, null, boundSql);
//处理查询总数,返回true时继续分页查询,false时直接返回
if (!dialect.afterCount(count, parameter, rowBounds)) {
//当查询总数为0时,直接返回空的结果
return dialect.afterPage(new ArrayList(), parameter, rowBounds);
}
}
resultList = ExecutorUtil.pageQuery(dialect, executor,
ms, parameter, rowBounds, resultHandler, boundSql, cacheKey);
} else {
//rowBounds有参数值,不使用分页插件处理时,仍然支持默认的内存分页
resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
}
// 将查询结果设置到Page对象中
return dialect.afterPage(resultList, parameter, rowBounds);
} finally {
if(dialect != null){
dialect.afterAll();
}
}
}