由于Ibatis的分页采用逻辑分页通过针对Ibatis分页的特殊处理支持物理分页。
实现思路:由于Ibatis各种数据操纵最终要调用SqlExecutor实现各种数据操作的功能。通过重写SqlExecutor 中特定的方法实现,相关的功能。
在SqlExecutor 源码中通过逻辑分页调用
public void executeQuery(StatementScope statementScope, Connection conn, String sql, Object parameters[], int skipResults, int maxResults, RowHandlerCallback callback)
throws SQLException;
通过自定义扩展的Ibatis的SqlExecutor类:
package com.framework.app.ibatis;
import java.sql.Connection;
import java.sql.SQLException;
import com.ibatis.sqlmap.engine.execution.SqlExecutor;
import com.ibatis.sqlmap.engine.mapping.statement.RowHandlerCallback;
import com.ibatis.sqlmap.engine.scope.StatementScope;
public class LimitSqlExecutor extends SqlExecutor {
private Dialect dialect;
private boolean enableLimit = true;
public Dialect getDialect() {
return dialect;
}
public void setDialect(Dialect dialect) {
if (dialect != null) {
System.out.println("[iBATIS] 设置 ibatis LimitSqlExecutor.dialect = "
+ dialect.getClass().getName());
}
this.dialect = dialect;
}
public boolean isEnableLimit() {
return enableLimit;
}
public void setEnableLimit(boolean enableLimit) {
this.enableLimit = enableLimit;
}
public void executeQuery(StatementScope request, Connection conn, String sql,
Object[] parameters, int skipResults, int maxResults,
RowHandlerCallback callback) throws SQLException {
String limitSql = sql;
int changedSkipResults = skipResults;
int changedMaxResults = maxResults;
if (supportsLimit()
&& (skipResults != NO_SKIPPED_RESULTS || maxResults != NO_MAXIMUM_RESULTS)) {
limitSql = limitSql.trim();
if (dialect.supportsLimitOffset()) {
limitSql = dialect.getLimitString(sql, skipResults, maxResults);
changedSkipResults = NO_SKIPPED_RESULTS;
} else {
limitSql = dialect.getLimitString(sql, 0, maxResults);
}
changedMaxResults = NO_MAXIMUM_RESULTS;
}
super.executeQuery(request, conn, limitSql, parameters,
changedSkipResults, changedMaxResults, callback);
}
public boolean supportsLimit() {
if (enableLimit && dialect != null) {
return dialect.supportsLimit();
}
return false;
}
}
使用如下:
通过注入的方式将重新自定的LimitSqlExecutor注入的SqlExecutor
@Override @SuppressWarnings({ "unchecked", "deprecation" }) public Pagination queryForPaginatedList(String itemSqlId, String countSqlId, Object parameter, int skip, int max) { if (sqlMapClient instanceof ExtendedSqlMapClient) { LimitSqlExecutor limitSqlExecutor = new LimitSqlExecutor(); limitSqlExecutor.setDialect(new OracleDialect()); RefUtils.setFieldValue(((ExtendedSqlMapClient) sqlMapClient) .getDelegate(), "sqlExecutor", SqlExecutor.class, limitSqlExecutor); } try { // 偏移值 int offset = (skip - 1) * max; // 数据项 List listItem = sqlMapClient.queryForList(itemSqlId, parameter, offset, max); // 总页数 int totalResult = queryForTotalResult(countSqlId, parameter); return new Pagination(listItem, totalResult, offset, max); } catch (SQLException e) { e.printStackTrace(); throw new DAOException(e); } }
备注:这种方法不是很好,但是考虑到执行分页的方法不是很多,所以就这样了,最好采用在类加载器类对垒的重新加载时注入相关的类,可能更好。