[DB][MyBatis]利用mybatis-paginator实现分页(目前看到MyBatis下最好的分页实现)

利用mybatis-paginator实现分页

 

1、mybatis-paginator简介

mybatis-paginator是gethub上的一个开源项目、用于java后台获取分页数据、该开源项目还提供一个列表组件(mmgrid)用于前端展示。

该开源项目地址:https://github.com/miemiedev

 

2、该开源项目的使用说明:

Maven中加入依赖:

[html]  view plain copy
  1. <dependencies>  
  2.   ...  
  3.     <dependency>  
  4.         <groupId>com.github.miemiedev</groupId>  
  5.         <artifactId>mybatis-paginator</artifactId>  
  6.         <version>1.2.10</version>  
  7.     </dependency>  
  8.   ...  
  9. </dependencies>  


Mybatis配置文件添加分页插件:
  

[html]  view plain copy
  1. <?xmlversionxmlversion="1.0"encoding="UTF-8"?>  
  2. <!DOCTYPE configuration  PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN"  "http://ibatis.apache.org/dtd/ibatis-3-config.dtd">  
  3. <configuration>  
  4.     <plugins>  
  5.         <plugin interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor">  
  6.             <propertynamepropertyname="dialectClass"value="com.github.miemiedev.mybatis.paginator.dialect.OracleDialect"/>  
  7.         </plugin>  
  8.      </plugins>  
  9. </configuration>  


创建一个查询,内容可以是任何Mybatis表达式,包括foreach和if等:

[html]  view plain copy
  1. <selectidselectid="findByCity"resultType="map">  
  2.     select * from TEST_USER where city = #{city};  
  3. </select>  


Dao中的方法或许是这样(用接口也是类似):

[java]  view plain copy
  1. public List findByCity(String city, PageBounds pageBounds){  
  2.     Map<String, Object> params =new HashMap<String, Object>();  
  3.     params.put("city",city);  
  4.     returngetSqlSession().selectList("db.table.user.findByCity", params, pageBounds);  
  5. }  


调用方式(分页加多列排序):

[java]  view plain copy
  1. int page = 1//页号  
  2. int pageSize = 20//每页数据条数  
  3. String sortString = "age.asc,gender.desc";//如果你想排序的话逗号分隔可以排序多列  
  4.   
  5. PageBounds pageBounds = newPageBounds(page, pageSize , Order.formString(sortString));  
  6.   
  7. List list = findByCity("BeiJing",pageBounds);  
  8.   
  9. //获得结果集条总数  
  10. PageList pageList = (PageList)list;  
  11. System.out.println("totalCount: "+ pageList.getPaginator().getTotalCount());  

 

PageList类是继承于ArrayList的,这样Dao中就不用为了专门分页再多写一个方法。

使用PageBounds这个对象来控制结果的输出,常用的使用方式一般都可以通过构造函数来配置。

[java]  view plain copy
  1. new PageBounds();//默认构造函数不提供分页,返回ArrayList  
  2. new PageBounds(int limit);//取TOPN操作,返回ArrayList  
  3. new PageBounds(Order... order);//只排序不分页,返回ArrayList  
  4. new PageBounds(int page, int limit);//默认分页,返回PageList  
  5. new PageBounds(int page, int limit, Order... order);//分页加排序,返回PageList  
  6. new PageBounds(int page, int limit, List<Order> orders,boolean containsTotalCount);//使用containsTotalCount来决定查不查询totalCount,即返回ArrayList还是PageList  


 

=========================================

如果用的是Spring MVC的话可以把JSON的配置写成这样:

[html]  view plain copy
  1. <mvc:annotation-driven>  
  2.     <mvc:message-converters register-defaults="true">  
  3.         <bean class="org.springframework.http.converter.StringHttpMessageConverter">  
  4.             <constructor-argvalueconstructor-argvalue="UTF-8"/>          
  5.         </bean>  
  6.    
  7.         <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">  
  8.              <property name="objectMapper">  
  9.                  <bean class="com.github.miemiedev.mybatis.paginator.jackson2.PageListJsonMapper"/>  
  10.              </property>  
  11.          </bean>  
  12.      </mvc:message-converters>  
  13.  </mvc:annotation-driven>  

那么在Controller就可以这样用了:

[java]  view plain copy
  1. @ResponseBody  
  2. @RequestMapping(value ="/findByCity.json")  
  3. public List findByCity(@RequestParam String city,  
  4.                  @RequestParam(required =false,defaultValue ="1") intpage,  
  5.                  @RequestParam(required =false,defaultValue ="30") intlimit,  
  6.                  @RequestParam(required =false) String sort,  
  7.                  @RequestParam(required =false) String dir) {  
  8.    
  9.     return userService.findByCity(city, newPageBounds(page, limit, Order.create(sort,dir)));  
  10. }  
  11.    
 


然后序列化后的JSON字符串就会变成这样的:

[javascript]  view plain copy
  1. {  
  2.     "items":[  
  3.         {"NAME":"xiaoma","AGE":30,"GENDER":1,"ID":3,"CITY":"BeiJing"},  
  4.         {"NAME":"xiaoli","AGE":30,"SCORE":85,"GENDER":1,"ID":1,"CITY":"BeiJing"},  
  5.         {"NAME":"xiaowang","AGE":30,"SCORE":92,"GENDER":0,"ID":2,"CITY":"BeiJing"},  
  6.         {"NAME":"xiaoshao","AGE":30,"SCORE":99,"GENDER":0,"ID":4,"CITY":"BeiJing"}  
  7.     ],  
  8.   
  9.     "slider": [1, 2, 3, 4, 5, 6, 7],  
  10.     "hasPrePage":false,  
  11.     "startRow": 1,  
  12.     "offset": 0,  
  13.     "lastPage":false,  
  14.     "prePage": 1,  
  15.     "hasNextPage":true,  
  16.     "nextPage": 2,  
  17.     "endRow": 30,  
  18.     "totalCount": 40351,  
  19.     "firstPage":true,  
  20.     "totalPages": 1346,  
  21.     "limit": 30,  
  22.     "page": 1  
  23. }  

 

=========================================

在SpringMVC中使用JSTL的话可以参考一下步骤(懒人用法)

在Spring配置文件中加入拦截器,或则参考拦截器实现定义自己的拦截器

[html]  view plain copy
  1. <mvc:interceptors>  
  2.     <mvc:interceptor>  
  3.         <mvc:mapping path="/**"/>  
  4.         <bean class="com.github.miemiedev.mybatis.paginator.springmvc.PageListAttrHandlerInterceptor"/>  
  5.     </mvc:interceptor>  
  6. </mvc:interceptors>  

 

然后Controller方法可以这样写

[java]  view plain copy
  1. @RequestMapping(value ="/userView.action")  
  2. public ModelAndView userView(@RequestParam String city,  
  3.                  @RequestParam(required =false,defaultValue ="1")intpage,  
  4.                  @RequestParam(required =false,defaultValue ="30")intlimit,  
  5.                  @RequestParam(required =false) String sort,  
  6.                  @RequestParam(required =false) String dir) {  
  7.     List users = userService.findByCity(city,newPageBounds(page, limit, Order.create(sort,dir)));  
  8.     returnnewModelAndView("account/user","users", users);  
  9. }  

 

JSP中就可以这样用了,拦截器会将PageList分拆添加Paginator属性,默认命名规则为"原属性名称"+"Paginator"

[html]  view plain copy
  1. <table>  
  2.     <c:forEach items="${users}"var="user">  
  3.         <tr>  
  4.             <td>${user['ID']}</td>  
  5.             <td>${user['NAME']}</td>  
  6.             <td>${user['AGE']}</td>  
  7.         </tr>  
  8.     </c:forEach>  
  9. </table>  
  10.   
  11. 上一页: ${usersPaginator.prePage}   
  12. 当前页: ${usersPaginator.page}   
  13. 下一页: ${usersPaginator.nextPage}   
  14. 总页数: ${usersPaginator.totalPages}   
  15. 总条数: ${usersPaginator.totalCount}   
  16.   
  17.   
  18. 更多属性参考Paginator类提供的方法  

 

=========================================

如果用如下方法设置pageBounds,当前这个查询就可以用两个线程同时查询list和totalCount了

pageBounds.setAsyncTotalCount(true);

如果所有的分页查询都是用异步的方式查询list和totalCount,可以在插件配置加入asyncTotalCount属性

[html]  view plain copy
  1. <plugin interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor">  
  2.     <property name="dialectClass" value="com.github.miemiedev.mybatis.paginator.dialect.OracleDialect"/>  
  3.     <property name="asyncTotalCount" value="true"/>  
  4. </plugin>  

但是你仍然可以用下面代码强制让这个查询不用异步

[java]  view plain copy
  1. pageBounds.setAsyncTotalCount(false);  

 

当然需要注意的是,只要你用到了异步查询,由于里面使用了线程池,所以在使用时就要加入清理监听器,以便在停止服务时关闭线程池。需要在web.xml中加入

[html]  view plain copy
  1. <listener>  
  2.     <listener-class>com.github.miemiedev.mybatis.paginator.CleanupMybatisPaginatorListener</listener-class>  
  3. </listener>  

 

你可能感兴趣的:([DB][MyBatis]利用mybatis-paginator实现分页(目前看到MyBatis下最好的分页实现))