Mybatis学习七 (分页)
1.分页的概念
例如,在数据库的某个表里有1000条数据,
我们每次只显示100条数据,在第1页显示第0到第99条,
在第2页显示第100到199条,依次类推,这就是分页。
分页可以分为逻辑分页和物理分页。
逻辑分页是我们的程序在显示每页的数据时,
首先查询得到表中的1000条数据,然后成熟根据当前页的“页码”选出其中的100条数据来显示。
物理分页是程序先判断出该选出这1000条的第几条到第几条,
然后数据库根据程序给出的信息查询出程序需要的100条返回给我们的程序。
2.MyBatis 物理分页
实现逻辑分页:
MyBatis使用RowBounds实现的分页是逻辑分页,
也就是先把数据记录全部查询出来,然在再根据 offset 和 limit 截断记录返回。
物理分页
为了在数据库层面上实现物理分页,又不改变原来 MyBatis 的函数逻辑,
可以编写 plugin 截获 MyBatis Executor 的 statementhandler,重写SQL来执行查询。
3.开发步骤
第一步:示例功能描述
使用 MyBatis和Spring MVC整合完成分页,完成这样的一个简单功能,即指定一个用户(ID=1),
查询出这个用户关联的所有订单分页显示出来(使用的数据库是:MySQL)
第二步:创建工程
Configuration.xml
applicationContext.xml
第三步:数据库表结构及数据记录

第四步:实例对象


第五步:配置文件
applicationContext.xml

Configuration.xml

UserMaper.xml

第六步:测试执行,输出结果

工具类:PagePlugin.java,Page.java, PageHelper.java,其中 PagePlugin 是针对 MyBatis 分页的插件。
PagePlugin:
@Intercepts( { @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class PagePlugin implements Interceptor {
private static String dialect = "";
private static String pageSqlId = "";
@SuppressWarnings("unchecked")
public Object intercept(Invocation ivk) throws Throwable {
if (ivk.getTarget() instanceof RoutingStatementHandler) {
RoutingStatementHandler statementHandler = (RoutingStatementHandler) ivk
.getTarget();
BaseStatementHandler delegate = (BaseStatementHandler) ReflectHelper
.getValueByFieldName(statementHandler, "delegate");
MappedStatement mappedStatement = (MappedStatement) ReflectHelper
.getValueByFieldName(delegate, "mappedStatement");
if (mappedStatement.getId().matches(pageSqlId)) {
BoundSql boundSql = delegate.getBoundSql();
Object parameterObject = boundSql.getParameterObject();
if (parameterObject == null) {
throw new NullYiibaierException("parameterObject error");
} else {
Connection connection = (Connection) ivk.getArgs()[0];
String sql = boundSql.getSql();
String countSql = "select count(0) from (" + sql
+ ") myCount";
System.out.println("总数sql 语句:" + countSql);
PreparedStatement countStmt = connection
.prepareStatement(countSql);
BoundSql countBS = new BoundSql(mappedStatement
.getConfiguration(), countSql, boundSql
.getParameterMappings(), parameterObject);
setParameters(countStmt, mappedStatement, countBS,
parameterObject);
ResultSet rs = countStmt.executeQuery();
int count = 0;
if (rs.next()) {
count = rs.getInt(1);
}
rs.close();
countStmt.close();
Page page = null;
if (parameterObject instanceof Page) {
page = (Page) parameterObject;
page.setTotalResult(count);
} else if (parameterObject instanceof Map) {
Map<String, Object> map = (Map<String, Object>) parameterObject;
page = (Page) map.get("page");
if (page == null)
page = new Page();
page.setTotalResult(count);
} else {
Field pageField = ReflectHelper.getFieldByFieldName(
parameterObject, "page");
if (pageField != null) {
page = (Page) ReflectHelper.getValueByFieldName(
parameterObject, "page");
if (page == null)
page = new Page();
page.setTotalResult(count);
ReflectHelper.setValueByFieldName(parameterObject,
"page", page);
} else {
throw new NoSuchFieldException(parameterObject
.getClass().getName());
}
}
String pageSql = generatePageSql(sql, page);
System.out.println("page sql:" + pageSql);
ReflectHelper.setValueByFieldName(boundSql, "sql", pageSql);
}
}
}
return ivk.proceed();
}
private void setParameters(PreparedStatement ps,
MappedStatement mappedStatement, BoundSql boundSql,
Object parameterObject) throws SQLException {
ErrorContext.instance().activity("setting parameters").object(
mappedStatement.getParameterMap().getId());
List<ParameterMapping> parameterMappings = boundSql
.getParameterMappings();
if (parameterMappings != null) {
Configuration configuration = mappedStatement.getConfiguration();
TypeHandlerRegistry typeHandlerRegistry = configuration
.getTypeHandlerRegistry();
MetaObject metaObject = parameterObject == null ? null
: configuration.newMetaObject(parameterObject);
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
PropertyTokenizer prop = new PropertyTokenizer(propertyName);
if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry
.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (propertyName
.startsWith(ForEachSqlNode.ITEM_PREFIX)
&& boundSql.hasAdditionalParameter(prop.getName())) {
value = boundSql.getAdditionalParameter(prop.getName());
if (value != null) {
value = configuration.newMetaObject(value)
.getValue(
propertyName.substring(prop
.getName().length()));
}
} else {
value = metaObject == null ? null : metaObject
.getValue(propertyName);
}
TypeHandler typeHandler = parameterMapping.getTypeHandler();
if (typeHandler == null) {
throw new ExecutorException(
"There was no TypeHandler found for parameter "
+ propertyName + " of statement "
+ mappedStatement.getId());
}
typeHandler.setParameter(ps, i + 1, value, parameterMapping
.getJdbcType());
}
}
}
}
private String generatePageSql(String sql, Page page) {
if (page != null && (dialect != null || !dialect.equals(""))) {
StringBuffer pageSql = new StringBuffer();
if ("mysql".equals(dialect)) {
pageSql.append(sql);
pageSql.append(" limit " + page.getCurrentResult() + ","
+ page.getShowCount());
} else if ("oracle".equals(dialect)) {
pageSql
.append("select * from (select tmp_tb.*,ROWNUM row_id from (");
pageSql.append(sql);
pageSql.append(") tmp_tb where ROWNUM<=");
pageSql.append(page.getCurrentResult() + page.getShowCount());
pageSql.append(") where row_id>");
pageSql.append(page.getCurrentResult());
}
return pageSql.toString();
} else {
return sql;
}
}
public Object plugin(Object arg0) {
// TODO Auto-generated method stub
return Plugin.wrap(arg0, this);
}
public void setProperties(Properties p) {
dialect = p.getProperty("dialect");
if (dialect == null || dialect.equals("")) {
try {
throw new PropertyException("dialect property is not found!");
} catch (PropertyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
pageSqlId = p.getProperty("pageSqlId");
if (dialect == null || dialect.equals("")) {
try {
throw new PropertyException("pageSqlId property is not found!");
} catch (PropertyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
结果:

学习来源:https://www.yiibai.com/mybatis/mybatis_pagination.html#article-start

浙公网安备 33010602011771号