Mybatis 邏輯分頁原理解析rowbounds
阿新 • • 發佈:2018-12-31
Mybatis提供了一個簡單的邏輯分頁使用類RowBounds(物理分頁當然就是我們在sql語句中指定limit和offset值),在DefaultSqlSession提供的某些查詢介面中我們可以看到RowBounds是作為引數用來進行分頁的,如下介面:
- public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds)
RowBounds原始碼如下:
- publicclass RowBounds {
- /* 預設offset是0**/
- publicstaticfinal
- /* 預設Limit是int的最大值,因此它使用的是邏輯分頁**/
- publicstaticfinalint NO_ROW_LIMIT = Integer.MAX_VALUE;
- publicstaticfinal RowBounds DEFAULT = new RowBounds();
- privateint offset;
- privateint 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;
- }
- publicint getOffset() {
- return offset;
- }
- publicint getLimit() {
- return limit;
- }
- }
在DefaultResultSetHandler中,邏輯分頁會將所有的結果都查詢到,然後根據RowBounds中提供的offset和limit值來獲取最後的結果,DefaultResultSetHandler實現如下:
- privatevoid handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
- throws SQLException {
- DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();
- //跳過RowBounds設定的offset值
- skipRows(rsw.getResultSet(), rowBounds);
- //判斷資料是否小於limit,如果小於limit的話就不斷的迴圈取值
- 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());
- }
- }
- privateboolean shouldProcessMoreRows(ResultContext<?> context, RowBounds rowBounds) throws SQLException {
- //判斷資料是否小於limit,小於返回true
- return !context.isStopped() && context.getResultCount() < rowBounds.getLimit();
- }
- //跳過不需要的行,應該就是rowbounds設定的limit和offset
- privatevoid 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 {
- //跳過RowBounds中設定的offset條資料
- for (int i = 0; i < rowBounds.getOffset(); i++) {
- rs.next();
- }
- }
- }