背景:某个场景是需要进行列表的分页展示;采用的方案是通过mybatis的逻辑分页RowBounds实现,其中limit的值是20,offset取的是(page-1)乖以limit;当page为1时得到的数据是正常的,但是当page大于1时得到的数据偏移量确是从page乘以200后开始的,和实际想得到的数据完全不匹配;
原因分析:mybatis逻辑分页的实现原理是先取出所有符合查询条件的数据,然后舍弃掉前面offset条的数据,再从剩下的数据中取出limit条;
private void 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());
}
}
private boolean shouldProcessMoreRows(ResultContext<?> context, RowBounds rowBounds) throws SQLException {
//判断数据是否小于limit,小于返回true
return !context.isStopped() && context.getResultCount() < rowBounds.getLimit();
}
//跳过不需要的行,应该就是rowbounds设置的limit和offset
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 {
//跳过RowBounds中设置的offset条数据
for (int i = 0; i < rowBounds.getOffset(); i++) {
rs.next();
}
}
}