分页是项目中经常会使用到的功能,我们可以自己手动在sql语句中进行分页,但是这样比较麻烦,Mybatis的PageHelper插件可以很好的帮助我们实现分页功能。
添加maven依赖
在对应工程的pom.xml文件中添加
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.0.0</version>
</dependency>
配置拦截器
在mybatis-config.xml文件中添加分页插件
<plugins>
<!-- com.github.pagehelper为PageHelper类所在包名 -->
<plugin interceptor="com.github.pagehelper.PageHelper">
<!-- 4.0.0以后版本可以不设置该参数 -->
<property name="dialect" value="mysql"/>
<!-- 该参数默认为false -->
<!-- 设置为true时,会将RowBounds第一个参数offset当成pageNum页码使用 -->
<!-- 和startPage中的pageNum效果一样-->
<property name="offsetAsPageNum" value="true"/>
<!-- 该参数默认为false -->
<!-- 设置为true时,使用RowBounds分页会进行count查询 -->
<property name="rowBoundsWithCount" value="true"/>
<!-- 设置为true时,如果pageSize=0或者RowBounds.limit = 0就会查询出全部的结果 -->
<!-- (相当于没有执行分页查询,但是返回结果仍然是Page类型)
<property name="pageSizeZero" value="true"/>-->
<!-- 3.3.0版本可用 - 分页参数合理化,默认false禁用 -->
<!-- 启用合理化时,如果pageNum<1会查询第一页,如果pageNum>pages会查询最后一页 -->
<!-- 禁用合理化时,如果pageNum<1或pageNum>pages会返回空数据 -->
<property name="reasonable" value="true"/>
<!-- 3.5.0版本可用 - 为了支持startPage(Object params)方法 -->
<!-- 增加了一个`params`参数来配置参数映射,用于从Map或ServletRequest中取值 -->
<!-- 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默认值 -->
<!-- 不理解该含义的前提下,不要随便复制该配置
<property name="params" value="pageNum=start;pageSize=limit;"/> -->
</plugin>
</plugins>
参数配置选择
列举一些可能会用到某些参数的场景
- 分页插件对RowBounds支持和Mybatis默认的方式是一致的,默认情况下不会进行count查询,如果想在分页查询时进行count查询,以及使用更强大的PageInfo类,需要设置该参数为true
- 如果觉得RowBounds中的两个参数offset和limit不如pageNum和PageSize容易理解,可以设置offsetAsPageNum参数为true,offset会当成pageNum使用,limit和pageSize含义相同
- 如果即使使用了分页,但是仍然想通过控制参数查询出全部的结果,可以设置pageSizeZero为true,就可以通过设置pageSize=0或者RowBounds.limt=0查询出全部的结果
- 如果在使用分页查看列表式的数据时,希望用户输入的页码即使不在合法范围内(第一页到最后一页之外),也能够看到正确的结果,可以设置reasonable为true,这时如果pageNum<1会查询第一页,pageNum>总页码会查询最后一页
具体使用
RowBounds方式调用
使用这种调用方式时,用RowBounds参数进行分页,侵入性最小,只是使用了这个参数,没有增加其他内容。当分页插件检测到使用了RowBounds参数时,就会对该查询进行物理分页
public DaoQueryResultVO<MemberBasicEntity> queryList(MemberBasicEntity entity, int startPage, int pageSize) throws CcpException
{
SqlSession sqlSession = CcpDB.getInstance().getSession();
Map<String, Object> map = new HashMap<String, Object>();
try
{
String statement = TMemberDAO.NAME_SPACE + ".queryList";//映射sql的标识字符串
if (entity != null)
{
map.put("tMember", entity.getMember());
map.put("tClub", entity.getMainClub());
}
List<MemberBasicEntity> list = sqlSession.selectList(statement, map, new RowBounds(startPage, pageSize));
return new DaoQueryResultVO<MemberBasicEntity>(list);
}
catch (Exception e)
{
CcpLogger.getInstance().error(e, "TMemberDAO.queryList, " + map);
throw new CcpException(CcpErrorCode.ERROR_MEMBER_DAO_DB_ERROR, e);
}
finally
{
CcpDB.getInstance().closeSession();
}
}
因为分页查询结果返回的是一个Page对象,Page对象继承自ArrayList,同时自身也扩展了属性。但如果我们直接返回Page对象的话,在一些场景下会遇到问题,比如JSON处理Page类型的结果时,会被当成List来JSON格式化,就会丢弃Page对象的所有扩展属性。所以这里我们将分页的结果Page类型转换成我们自己定义的一个类型DaoQueryResultVO,它继承自PageInfo,包含了一个List属性来保存分页查询出来的结果。PageInfo是插件提供给我们的,可以作为返回值,这里我们再用DaoQueryResultVO继续封装了一下,将PageInfo中的结果集由Page类型转换为ArrayList类型
public class DaoQueryResultVO<T> extends PageInfo<T> implements Serializable
{
private static final long serialVersionUID = -6401449740378930924L;
private List<T> lstResultList;
public DaoQueryResultVO(List<T> list)
{
super(list);
if (getSize() >= 0)
{
lstResultList = new ArrayList<T>();
lstResultList.addAll(getList().subList(0, getSize()));
}
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
return "DaoQueryResultVO [lstResultList=" + lstResultList + ", toString()=" + super.toString() + "]";
}
/**
* @return the lstResultList
*/
public List<T> getLstResultList()
{
return lstResultList;
}
}
PageHelper.startPage静态方法调用
在需要进行分页的方法前调用PageHelper.startPage静态方法即可,紧跟在这个方法后的第一个查询方法会被进行分页