ibatis 分页实现原理

项目中要到了ibatis 发现分页性能低下,所以看了一下源码,不禁一个寒战,下面发出来简单分析一下,如有错处还请指定。。
下面看ibatis最终查询方法
/**
*
* @param statementScope statement对象
* @param rs 数据集合
* @param skipResults 数据开始位置
* @param maxResults 数据结束位置
* @param callback 数据返回(封装)对象
* @throws SQLException
*/
private void handleResults(StatementScope statementScope, ResultSet rs, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException {
try {
statementScope.setResultSet(rs);
ResultMap resultMap = statementScope.getResultMap();
if (resultMap != null) {
// Skip Results
if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {
if (skipResults > 0) {
rs.absolute(skipResults);
}
} else {
for (int i = 0; i < skipResults; i++) {
if (!rs.next()) {
return;
}
}
}

// Get Results
int resultsFetched = 0;
while ((maxResults == SqlExecutor.NO_MAXIMUM_RESULTS || resultsFetched < maxResults) && rs.next()) {
Object[] columnValues = resultMap.resolveSubMap(statementScope, rs).getResults(statementScope, rs);
callback.handleResultObject(statementScope, columnValues, rs);
resultsFetched++;
}
}
} finally {
statementScope.setResultSet(null);
}
}
}

statementScope对象获取方式,ID为字符串参数,原来是ibatis的sessionscope中启动一个statement
MappedStatement ms = getMappedStatement(id);
StatementScope statementScope = beginStatementScope(sessionScope, ms);


再看rs如何来的,如下
ResultSet rs;
rs = getFirstResultSet(statementScope, ps);

再看getFirstResultSet获取记录集的方法,而getResultSet方法确实获取当前statement的所有数据。
private ResultSet getFirstResultSet(StatementScope scope, Statement stmt) throws SQLException {
ResultSet rs = null;
boolean hasMoreResults = true;
while (hasMoreResults) {
rs = stmt.getResultSet();
if (rs != null) {
break;
}
hasMoreResults = moveToNextResultsIfPresent(scope, stmt);
}
return rs;
}
看到这里有些失望,难道记录集是这样获取的。。。。


再回头看handleResults方法,rs.absolute(skipResults); 设定游标点,超大记录集时候这个方法显得和愚笨!!
再看更有意思的方法:是检测数据是否有效性的。
for (int i = 0; i < skipResults; i++) {
if (!rs.next()) {
return;
}
}
如果开始点是100亿呢,那么循环这个次数,我不说性能了,大家也能看出来。睡个觉再来看结果来吧。如果能成功,下一条rs.next()继续循环去吧,循环不是错!!
这还不算完这是查询检测数据而已,还没有整理要返回的数据。。。。
while ((maxResults == SqlExecutor.NO_MAXIMUM_RESULTS || resultsFetched < maxResults) && rs.next()) {
Object[] columnValues = resultMap.resolveSubMap(statementScope, rs).getResults(statementScope, rs);
callback.handleResultObject(statementScope, columnValues, rs);
resultsFetched++;
}
又一次无知的循环。。。如果循环到想要的记录,就吧记录添加到另外一个对象中。
到此获取“数据next分页”已经差不多实现了。。。。

本人亲身做过实验,每页20条记录,第一页1秒(可能网络有消耗)2万页的时候需要20秒,20万页的时候程序直接死掉。实现就这么无情的被 while 掉了。。。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值