分頁(yè)是項(xiàng)目中經(jīng)常會(huì)使用到的功能,我們可以自己手動(dòng)在sql語(yǔ)句中進(jìn)行分頁(yè),但是這樣比較麻煩,Mybatis的PageHelper插件可以很好的幫助我們實(shí)現(xiàn)分頁(yè)功能。
添加maven依賴
在對(duì)應(yīng)工程的pom.xml文件中添加
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.0.0</version>
</dependency>
配置攔截器
在mybatis-config.xml文件中添加分頁(yè)插件
<plugins>
<!-- com.github.pagehelper為PageHelper類(lèi)所在包名 -->
<plugin interceptor="com.github.pagehelper.PageHelper">
<!-- 4.0.0以后版本可以不設(shè)置該參數(shù) -->
<property name="dialect" value="mysql"/>
<!-- 該參數(shù)默認(rèn)為false -->
<!-- 設(shè)置為true時(shí),會(huì)將RowBounds第一個(gè)參數(shù)offset當(dāng)成pageNum頁(yè)碼使用 -->
<!-- 和startPage中的pageNum效果一樣-->
<property name="offsetAsPageNum" value="true"/>
<!-- 該參數(shù)默認(rèn)為false -->
<!-- 設(shè)置為true時(shí),使用RowBounds分頁(yè)會(huì)進(jìn)行count查詢 -->
<property name="rowBoundsWithCount" value="true"/>
<!-- 設(shè)置為true時(shí),如果pageSize=0或者RowBounds.limit = 0就會(huì)查詢出全部的結(jié)果 -->
<!-- (相當(dāng)于沒(méi)有執(zhí)行分頁(yè)查詢,但是返回結(jié)果仍然是Page類(lèi)型)
<property name="pageSizeZero" value="true"/>-->
<!-- 3.3.0版本可用 - 分頁(yè)參數(shù)合理化,默認(rèn)false禁用 -->
<!-- 啟用合理化時(shí),如果pageNum<1會(huì)查詢第一頁(yè),如果pageNum>pages會(huì)查詢最后一頁(yè) -->
<!-- 禁用合理化時(shí),如果pageNum<1或pageNum>pages會(huì)返回空數(shù)據(jù) -->
<property name="reasonable" value="true"/>
<!-- 3.5.0版本可用 - 為了支持startPage(Object params)方法 -->
<!-- 增加了一個(gè)`params`參數(shù)來(lái)配置參數(shù)映射,用于從Map或ServletRequest中取值 -->
<!-- 可以配置pageNum,pageSize,count,pageSizeZero,reasonable,不配置映射的用默認(rèn)值 -->
<!-- 不理解該含義的前提下,不要隨便復(fù)制該配置
<property name="params" value="pageNum=start;pageSize=limit;"/> -->
</plugin>
</plugins>
參數(shù)配置選擇
列舉一些可能會(huì)用到某些參數(shù)的場(chǎng)景
- 分頁(yè)插件對(duì)RowBounds支持和Mybatis默認(rèn)的方式是一致的,默認(rèn)情況下不會(huì)進(jìn)行count查詢,如果想在分頁(yè)查詢時(shí)進(jìn)行count查詢,以及使用更強(qiáng)大的PageInfo類(lèi),需要設(shè)置該參數(shù)為true
- 如果覺(jué)得RowBounds中的兩個(gè)參數(shù)offset和limit不如pageNum和PageSize容易理解,可以設(shè)置offsetAsPageNum參數(shù)為true,offset會(huì)當(dāng)成pageNum使用,limit和pageSize含義相同
- 如果即使使用了分頁(yè),但是仍然想通過(guò)控制參數(shù)查詢出全部的結(jié)果,可以設(shè)置pageSizeZero為true,就可以通過(guò)設(shè)置pageSize=0或者RowBounds.limt=0查詢出全部的結(jié)果
- 如果在使用分頁(yè)查看列表式的數(shù)據(jù)時(shí),希望用戶輸入的頁(yè)碼即使不在合法范圍內(nèi)(第一頁(yè)到最后一頁(yè)之外),也能夠看到正確的結(jié)果,可以設(shè)置reasonable為true,這時(shí)如果pageNum<1會(huì)查詢第一頁(yè),pageNum>總頁(yè)碼會(huì)查詢最后一頁(yè)
具體使用
RowBounds方式調(diào)用
使用這種調(diào)用方式時(shí),用RowBounds參數(shù)進(jìn)行分頁(yè),侵入性最小,只是使用了這個(gè)參數(shù),沒(méi)有增加其他內(nèi)容。當(dāng)分頁(yè)插件檢測(cè)到使用了RowBounds參數(shù)時(shí),就會(huì)對(duì)該查詢進(jìn)行物理分頁(yè)
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的標(biāo)識(shí)字符串
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();
}
}
因?yàn)榉猪?yè)查詢結(jié)果返回的是一個(gè)Page對(duì)象,Page對(duì)象繼承自ArrayList,同時(shí)自身也擴(kuò)展了屬性。但如果我們直接返回Page對(duì)象的話,在一些場(chǎng)景下會(huì)遇到問(wèn)題,比如JSON處理Page類(lèi)型的結(jié)果時(shí),會(huì)被當(dāng)成List來(lái)JSON格式化,就會(huì)丟棄Page對(duì)象的所有擴(kuò)展屬性。所以這里我們將分頁(yè)的結(jié)果Page類(lèi)型轉(zhuǎn)換成我們自己定義的一個(gè)類(lèi)型DaoQueryResultVO,它繼承自PageInfo,包含了一個(gè)List屬性來(lái)保存分頁(yè)查詢出來(lái)的結(jié)果。PageInfo是插件提供給我們的,可以作為返回值,這里我們?cè)儆肈aoQueryResultVO繼續(xù)封裝了一下,將PageInfo中的結(jié)果集由Page類(lèi)型轉(zhuǎn)換為ArrayList類(lèi)型
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靜態(tài)方法調(diào)用
在需要進(jìn)行分頁(yè)的方法前調(diào)用PageHelper.startPage靜態(tài)方法即可,緊跟在這個(gè)方法后的第一個(gè)查詢方法會(huì)被進(jìn)行分頁(yè)