由于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);
}
}
备注:这种方法不是很好,但是考虑到执行分页的方法不是很多,所以就这样了,最好采用在类加载器类对垒的重新加载时注入相关的类,可能更好。