mybatis实战教程之七:实现mybatis分页 (1)

发布时间:

百度文库-让每个人平等地提升自我!

mybatis实战教程(mybatisinaction之七:实现mybatis分页(源码下载

上一篇文章里已经讲到了mybatisspringMVC的集成,并且做了一个列表展示,显示出所有article列表,但没有用到分页,在实际的项目中,分页是肯定需要的。而且是物理分页,不是内存分页。对于物理分页方案,不同的数据库,有不同的实现方法,对于mysql就是利用limitoffset,pagesize方式来实现的。oracle是通过rownum来实现的,如果你熟悉相关数据库的操作,是一样的很好扩展,本文以mysql为例子来讲述.先看一下效果(源代码在文章最后提供下载:

实现mybatis物理分页,一个最简单的方式是,是在你的mapperSQL语句中直接写类似如下方式:程序代码
resultMap="resultUserArticleList">
selectuser.id,user.userName,user.userAddress,article.idaid,article.title,article.contentfromuser,article
whereuser.id=article.useridanduser.id=#{id}limit#{offset},#{pagesize}
1

百度文库-让每个人平等地提升自我!

请注意这里的parameterType是你传入的参数类,或者map里面包含了offset,pagesize,和其他你需要的参数,用这种方式,肯定可以实现分页。这是简单的一种方式。但更通用的一种方式是用mybatis插件的方式.参考了网上的很多资料mybatisplugin方面的资料。写自己的插件.
程序代码
packagecom.yihaomen.util;
importjava.lang.reflect.Field;importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.util.List;importjava.util.Map;importjava.util.Properties;
importjavax.xml.bind.PropertyException;
importorg.apache.ibatis.builder.xml.dynamic.ForEachSqlNode;importorg.apache.ibatis.executor.ErrorContext;importorg.apache.ibatis.executor.Executor;
importorg.apache.ibatis.executor.ExecutorException;
importorg.apache.ibatis.executor.statement.BaseStatementHandler;importorg.apache.ibatis.executor.statement.RoutingStatementHandler;importorg.apache.ibatis.executor.statement.StatementHandler;2

百度文库-让每个人平等地提升自我!

importorg.apache.ibatis.mapping.BoundSql;importorg.apache.ibatis.mapping.MappedStatement;importorg.apache.ibatis.mapping.ParameterMapping;importorg.apache.ibatis.mapping.ParameterMode;importorg.apache.ibatis.plugin.Interceptor;importorg.apache.ibatis.plugin.Intercepts;importorg.apache.ibatis.plugin.Invocation;importorg.apache.ibatis.plugin.Plugin;importorg.apache.ibatis.plugin.Signature;importorg.apache.ibatis.reflection.MetaObject;
importorg.apache.ibatis.reflection.property.PropertyTokenizer;importorg.apache.ibatis.session.Configuration;importorg.apache.ibatis.session.ResultHandler;importorg.apache.ibatis.session.RowBounds;importorg.apache.ibatis.type.TypeHandler;importorg.apache.ibatis.type.TypeHandlerRegistry;
@Intercepts({@Signature(type=StatementHandler.class,method="prepare",args={Connection.class}}
publicclassPagePluginimplementsInterceptor{
privatestaticStringdialect="";privatestaticStringpageSqlId="";
@SuppressWarnings("unchecked"
publicObjectintercept(InvocationivkthrowsThrowable{3

百度文库-让每个人平等地提升自我!

if(ivk.getTarget(instanceofRoutingStatementHandler{
RoutingStatementHandlerstatementHandler=(RoutingStatementHandlerivk
.getTarget(;
BaseStatementHandlerdelegate=(BaseStatementHandlerReflectHelper.getValueByFieldName(statementHandler,"delegate";
MappedStatementmappedStatement=(MappedStatementReflectHelper.getValueByFieldName(delegate,"mappedStatement";
if(mappedStatement.getId(.matches(pageSqlId{BoundSqlboundSql=delegate.getBoundSql(;
ObjectparameterObject=boundSql.getParameterObject(;if(parameterObject==null{
thrownewNullPointerException("parameterObjecterror";}else{
Connectionconnection=(Connectionivk.getArgs([0];Stringsql=boundSql.getSql(;
StringcountSql="selectcount(0from("+sql+"myCount";System.out.println("总数sql语句:"+countSql;PreparedStatementcountStmt=connection.prepareStatement(countSql;BoundSqlcountBS=newBoundSql(
mappedStatement.getConfiguration(,countSql,boundSql.getParameterMappings(,parameterObject;setParameters(countStmt,mappedStatement,countBS,4

百度文库-让每个人平等地提升自我!

parameterObject;
ResultSetrs=countStmt.executeQuery(;intcount=0;if(rs.next({
count=rs.getInt(1;}
rs.close(;countStmt.close(;
PageInfopage=null;
if(parameterObjectinstanceofPageInfo{page=(PageInfoparameterObject;page.setTotalResult(count;
}elseif(parameterObjectinstanceofMap{
Mapmap=(MapparameterObject;page=(PageInfomap.get("page";if(page==null
page=newPageInfo(;page.setTotalResult(count;}else{
FieldpageField=ReflectHelper.getFieldByFieldName(parameterObject,"page";if(pageField!=null{
page=(PageInfoReflectHelper.getValueByFieldName(parameterObject,"page";if(page==null5

百度文库-让每个人平等地提升自我!

page=newPageInfo(;page.setTotalResult(count;
ReflectHelper.setValueByFieldName(parameterObject,"page",page;}else{
thrownewNoSuchFieldException(parameterObject.getClass(.getName(;}}
StringpageSql=generatePageSql(sql,page;System.out.println("pagesql:"+pageSql;
ReflectHelper.setValueByFieldName(boundSql,"sql",pageSql;}}}
returnivk.proceed(;}
privatevoidsetParameters(PreparedStatementps,
MappedStatementmappedStatement,BoundSqlboundSql,ObjectparameterObjectthrowsSQLException{ErrorContext.instance(.activity("settingparameters".object(mappedStatement.getParameterMap(.getId(;ListparameterMappings=boundSql.getParameterMappings(;if(parameterMappings!=null{6

百度文库-让每个人平等地提升自我!

Configurationconfiguration=mappedStatement.getConfiguration(;TypeHandlerRegistrytypeHandlerRegistry=configuration.getTypeHandlerRegistry(;
MetaObjectmetaObject=parameterObject==null?null:configuration.newMetaObject(parameterObject;for(inti=0;i
ParameterMappingparameterMapping=parameterMappings.get(i;if(parameterMapping.getMode(!=ParameterMode.OUT{Objectvalue;
StringpropertyName=parameterMapping.getProperty(;PropertyTokenizerprop=newPropertyTokenizer(propertyName;if(parameterObject==null{value=null;
}elseif(typeHandlerRegistry
.hasTypeHandler(parameterObject.getClass({value=parameterObject;
}elseif(boundSql.hasAdditionalParameter(propertyName{value=boundSql.getAdditionalParameter(propertyName;}elseif(propertyName
.startsWith(ForEachSqlNode.ITEM_PREFIX
&&boundSql.hasAdditionalParameter(prop.getName({value=boundSql.getAdditionalParameter(prop.getName(;if(value!=null{
value=configuration.newMetaObject(value.getValue(
propertyName.substring(prop7

百度文库-让每个人平等地提升自我!

.getName(.length(;}}else{
value=metaObject==null?null:metaObject.getValue(propertyName;}
TypeHandlertypeHandler=parameterMapping.getTypeHandler(;if(typeHandler==null{thrownewExecutorException(
"TherewasnoTypeHandlerfoundforparameter"+propertyName+"ofstatement"+mappedStatement.getId(;}
typeHandler.setParameter(ps,i+1,value,parameterMapping.getJdbcType(;}}}}
privateStringgeneratePageSql(Stringsql,PageInfopage{if(page!=null&&(dialect!=null||!dialect.equals(""{StringBufferpageSql=newStringBuffer(;if("mysql".equals(dialect{pageSql.append(sql;8

百度文库-让每个人平等地提升自我!

pageSql.append("limit"+page.getCurrentResult(+","+page.getShowCount(;}elseif("oracle".equals(dialect{
pageSql.append("select*from(selecttmp_tb.*,ROWNUMrow_idfrom(";pageSql.append(sql;
pageSql.append("tmp_tbwhereROWNUM<=";
pageSql.append(page.getCurrentResult(+page.getShowCount(;pageSql.append("whererow_id>";pageSql.append(page.getCurrentResult(;}
returnpageSql.toString(;}else{returnsql;}}
publicObjectplugin(Objectarg0{//TODOAuto-generatedmethodstubreturnPlugin.wrap(arg0,this;}
publicvoidsetProperties(Propertiesp{dialect=p.getProperty("dialect";if(dialect==null||dialect.equals(""{try{
thrownewPropertyException("dialectpropertyisnotfound!";9

百度文库-让每个人平等地提升自我!

}catch(PropertyExceptione{//TODOAuto-generatedcatchblocke.printStackTrace(;}}
pageSqlId=p.getProperty("pageSqlId";if(dialect==null||dialect.equals(""{try{
thrownewPropertyException("pageSqlIdpropertyisnotfound!";}catch(PropertyExceptione{//TODOAuto-generatedcatchblocke.printStackTrace(;}}}}

此插件有两个辅助类:PageInfo,ReflectHelper,你可以下载源代码参考。
写了插件之后,当然需要在mybatis的配置文件Configuration.xml里配置这个插件程序代码



10

百度文库-让每个人平等地提升自我!



请注意,这个插件定义了一个规则,也就是在mappersql语句的id必须包含ListPage才能被拦截。否则将不会分页处理.
插件写好了,现在就可以在springmvc中的controller层中写一个方法来测试这个分页:程序代码
@RequestMapping("/pagelist"
publicModelAndViewpageList(HttpServletRequestrequest,HttpServletResponseresponse{
intcurrentPage=
request.getParameter("page"==null?1:Integer.parseInt(request.getParameter("page";
intpageSize=3;if(currentPage<=0{currentPage=1;}
intcurrentResult=(currentPage-1*pageSize;
System.out.println(request.getRequestURI(;System.out.println(request.getQueryString(;
PageInfopage=newPageInfo(;page.setShowCount(pageSize;page.setCurrentResult(currentResult;
11

百度文库-让每个人平等地提升自我!

List
articles=iUserOperation.selectArticleListPage(page,1;
System.out.println(page;
inttotalCount=page.getTotalResult(;
intlastPage=0;
if(totalCount%pageSize==0{lastPage=totalCount%pageSize;}else{
lastPage=1+totalCount/pageSize;}
if(currentPage>=lastPage{currentPage=lastPage;}
StringpageStr="";
pageStr=String.format("上一页下一页",
request.getRequestURI(+"?page="+(currentPage-1,request.getRequestURI(+"?page="+(currentPage+1;
12

百度文库-让每个人平等地提升自我!

//制定视图,也就是list.jsp
ModelAndViewmav=newModelAndView("list";mav.addObject("articles",articles;mav.addObject("pageStr",pageStr;returnmav;}

然后运行程序,进入分页页面,你就可以看到结果了:


13

mybatis实战教程之七:实现mybatis分页 (1)

相关推荐