逻辑分页
逻辑分页是强烈不推荐的,但是这里还是把用法写出来吧
Mybatis里面有一个逻辑分页对象RowBounds,里面主要有两个属性,offset和limit(从第几条开始,查询多少条)。我们可以在Mapper接口的方法上加上这个参数,不需要修改xml里面的SQL语句。
接口中定义
public List<User> queryUserList(RowBounds rowBounds);
测试类
@Test
public void test01() throws Exception{
init();
UserMapper mapper = session.getMapper(UserMapper.class);
// 设置分页的数据
RowBounds rowBounds = new RowBounds(1,3);
List<User> users = mapper.queryUserList(rowBounds);
for (User user : users) {
System.out.println(user);
}
}
RowBounds的工作原理其实是对ResultSet的处理。它会舍弃掉前面offset条数据,然后再取剩下的数据的limit条。
// DefaultResultSetHandler.java
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap
resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping
parentMapping) throws SQLException {
DefaultResultContext<Object> resultContext = new DefaultResultContext();
ResultSet resultSet = rsw.getResultSet();
this.skipRows(resultSet, rowBounds);
while(this.shouldProcessMoreRows(resultContext, rowBounds) &&
!resultSet.isClosed() && resultSet.next()) {
ResultMap discriminatedResultMap =
this.resolveDiscriminatedResultMap(resultSet, resultMap, (String)null);
Object rowValue = this.getRowValue(rsw, discriminatedResultMap,
(String)null);
this.storeObject(resultHandler, resultContext, rowValue, parentMapping,
resultSet);
}
}
很明显。如果数据量大的话,这种翻页方式会很低(跟查询到内存中再使用subList(start, end)没什么区别,所以我们要用到物理翻页。
物理分页
物理翻页是真正的翻页,它是通过数据库支持的语句来翻页。
第一种简单的办法就是传入参数(或者包装一个page对象),在SQL语句翻页。
<select id="selectUserPage" parameterType="map" resultMap="BaseResultMap">
select * from t_user limit #{curIndex} , #{pageSize}
</select>
第一个问题是我们在Java业务代码里面计算起止序号,第二个问题是:每个需要翻页的Statement都要编写limit语句,会造成Mapper映射器里面很多代码冗余。
那我们就需要一种通用的方式,不需要去修改配置的任何一条SQL,我们只要传入当前是第几页,每页多少条就可以了,自动计算出来起止序号。
我们最常用的做法就是使用翻页的插件,比如PageHelper。
// pageSize每一页几条
PageHelper.startPage(pn, 10);
List<Employee> emps = employeeService.getAll();
// navigatePages 导航页码数
PageInfo page = new PageInfo(emps, 10);
return Msg.success().add("pageInfo", page);
PageHelper是通过Mybatis的拦截器实现的,插件的具体原理我们后面的再分析。简单来说它会根据PageHelper的参数,改写我们SQL语句,比如MySQL会生成limit语句,Oracle会生成rownum语句,SQL Sever会生成top 语句。