1 默認(rèn)分頁(邏輯分頁)
MyBatis 默認(rèn)提供了分頁功能宋距,即 RowBounds 類轴踱,該類提供兩個(gè)參數(shù):offset 和 limit。offset 為起始行數(shù)谚赎,limit 為要查詢的行數(shù)淫僻。
public class RowBounds {
//other...
public static final int NO_ROW_OFFSET = 0;
public static final int NO_ROW_LIMIT = Integer.MAX_VALUE;
private final int offset;
private final int limit;
public RowBounds() {
this.offset = NO_ROW_OFFSET;
this.limit = NO_ROW_LIMIT;
}
public RowBounds(int offset, int limit) {
this.offset = offset;
this.limit = limit;
}
//other...
}
但使用 RowBounds 的默認(rèn)分頁是邏輯分頁:從數(shù)據(jù)庫一次性查詢出所有的記錄,再通過傳入的 RowBounds 的 offset 和 limit 的值壶唤,使用 for 循環(huán)進(jìn)行過濾雳灵。源碼如下:
org.apache.ibatis.executor.resultset.DefaultResultSetHandler 類:
private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
throws SQLException {
DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
skipRows(rsw.getResultSet(), rowBounds);
while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {
ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
Object rowValue = getRowValue(rsw, discriminatedResultMap);
storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());
}
}
private void skipRows(ResultSet rs, RowBounds rowBounds) throws SQLException {
if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {
if (rowBounds.getOffset() != RowBounds.NO_ROW_OFFSET) {
rs.absolute(rowBounds.getOffset());
}
} else {
for (int i = 0; i < rowBounds.getOffset(); i++) {
rs.next();
}
}
}
為了驗(yàn)證上面的邏輯,我們執(zhí)行下面的測試方法:
public void testDefaultPaging() {
SqlSession session = FactoryBuildByXML.getFactory().openSession(true);
try {
RowBounds rowBounds = new RowBounds(2, 11);
List<Object> list = session.selectList("com.zhaoxueer.learn.dao.AuthorMapper.selectAllTest", null, rowBounds);
System.out.println("查詢的結(jié)果數(shù):" + list.size());
} finally {
session.close();
}
}
AuthorMapper 中 selectAllTest 方法為:
@Select("select id, name, sex, phone from author")
List<Author> selectAllTest();
執(zhí)行結(jié)果為:
DEBUG [main] - ==> Preparing: select id, name, sex, phone from author
DEBUG [main] - ==> Parameters:
查詢的結(jié)果數(shù):11
這種分頁方式不能滿足我們對(duì)于減輕數(shù)據(jù)庫壓力的要求闸盔,因此不建議使用悯辙。
2 使用 pagehelper 插件(物理分頁)
為了簡單地實(shí)現(xiàn)真正的物理分頁,我們可以使用插件去實(shí)現(xiàn)迎吵,網(wǎng)上有很多這樣的插件躲撰,例如比較常用的 pagehelper 插件。
只需要簡單的三步:
- 第一步:maven 引入依賴:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>latest version</version>
</dependency>
注:修改 version 為最新的版本號(hào)(如 5.1.7)击费,可點(diǎn)擊上面鏈接查看最新版本拢蛋。
- 第二步:mybatis-config.xml 注冊(cè)該 plugin:
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor">
<!-- config params as the following -->
<!--<property name="param1" value="value1"/>-->
</plugin>
</plugins>
- 第三步:代碼中使用:
public void testPageHelper() {
SqlSession session = FactoryBuildByXML.getFactory().openSession(true);
try {
AuthorMapper authorMapper = session.getMapper(AuthorMapper.class);
// 只需要在查詢語句前插入該語句即可實(shí)現(xiàn)分頁
PageHelper.startPage(1, 10);
List<Author> authorList = authorMapper.selectAllTest();
System.out.println("查詢的結(jié)果數(shù):" + authorList.size());
} finally {
session.close();
}
}
執(zhí)行結(jié)果為:
DEBUG [main] - ==> Preparing: SELECT count(0) FROM author
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 1
DEBUG [main] - ==> Preparing: select id, name, sex, phone from author LIMIT ?
DEBUG [main] - ==> Parameters: 10(Integer)
DEBUG [main] - <== Total: 10
查詢的結(jié)果數(shù):10
注意:注入分頁插件 plugin 元素后,執(zhí)行前面默認(rèn)分頁舉例中的方法蔫巩,也會(huì)實(shí)現(xiàn)物理分頁谆棱,因?yàn)樵摬寮?duì)該方法也進(jìn)行了攔截處理。
pagehelper 插件的 PageInterceptor 類對(duì)以下方法進(jìn)行攔截:
@Intercepts(
{
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
}
)
默認(rèn)分頁舉例中的語句:
RowBounds rowBounds = new RowBounds(2, 11);
List<Object> list = session.selectList("com.zhaoxueer.learn.dao.AuthorMapper.selectAllTest", null, rowBounds);
對(duì)上面兩行代碼的執(zhí)行結(jié)果為:
DEBUG [main] - ==> Preparing: select id, name, sex, phone from author LIMIT ?, ?
DEBUG [main] - ==> Parameters: 2(Integer), 11(Integer)
DEBUG [main] - <== Total: 11
查詢的結(jié)果數(shù):11
因此圆仔,若要測試默認(rèn)分頁的邏輯分頁方式垃瞧,請(qǐng)注釋掉 plugin 代碼塊。
更多使用方法查看:MyBatis PageHelper 文檔
附:
當(dāng)前版本:mybatis-3.5.0
官網(wǎng)文檔:MyBatis
項(xiàng)目實(shí)踐:MyBatis Learn
手寫源碼:MyBatis 簡易實(shí)現(xiàn)