利用mybatis-paginator實現分頁
1、mybatis-paginator簡介
mybatis-paginator是gethub上的一個開源項目、用於java後台擷取分頁資料、該開源項目還提供一個列表組件(mmgrid)用於前端展示。
該開源項目地址:https://github.com/miemiedev
2、該開源項目的使用說明:
Maven中加入依賴:
<dependencies> ... <dependency> <groupId>com.github.miemiedev</groupId> <artifactId>mybatis-paginator</artifactId> <version>1.2.10</version> </dependency> ...</dependencies>
Mybatis設定檔添加分頁外掛程式:
<?xmlversion="1.0"encoding="UTF-8"?><!DOCTYPE configuration PUBLIC "-//ibatis.apache.org//DTD Config 3.0//EN" "http://ibatis.apache.org/dtd/ibatis-3-config.dtd"><configuration> <plugins> <plugin interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor"> <propertyname="dialectClass"value="com.github.miemiedev.mybatis.paginator.dialect.OracleDialect"/> </plugin> </plugins></configuration>
建立一個查詢,內容可以是任何Mybatis運算式,包括foreach和if等:
<selectid="findByCity"resultType="map"> select * from TEST_USER where city = #{city};</select>
Dao中的方法或許是這樣(用介面也是類似):
public List findByCity(String city, PageBounds pageBounds){ Map<String, Object> params =new HashMap<String, Object>(); params.put("city",city); returngetSqlSession().selectList("db.table.user.findByCity", params, pageBounds);}
調用方式(分頁加多列排序):
int page = 1; //頁號int pageSize = 20; //每頁資料條數String sortString = "age.asc,gender.desc";//如果你想排序的話逗號分隔可以排序多列PageBounds pageBounds = newPageBounds(page, pageSize , Order.formString(sortString));List list = findByCity("BeiJing",pageBounds);//獲得結果集條總數PageList pageList = (PageList)list;System.out.println("totalCount: "+ pageList.getPaginator().getTotalCount());
PageList類是繼承於ArrayList的,這樣Dao中就不用為了專門分頁再多寫一個方法。
使用PageBounds這個對象來控制結果的輸出,常用的使用方式一般都可以通過建構函式來配置。
new PageBounds();//預設建構函式不提供分頁,返回ArrayListnew PageBounds(int limit);//取TOPN操作,返回ArrayListnew PageBounds(Order... order);//只排序不分頁,返回ArrayListnew PageBounds(int page, int limit);//預設分頁,返回PageListnew PageBounds(int page, int limit, Order... order);//分頁加排序,返回PageListnew PageBounds(int page, int limit, List<Order> orders,boolean containsTotalCount);//使用containsTotalCount來決定查不查詢totalCount,即返回ArrayList還是PageList
=========================================
如果用的是Spring MVC的話可以把JSON的配置寫成這樣:
<mvc:annotation-driven> <mvc:message-converters register-defaults="true"> <bean class="org.springframework.http.converter.StringHttpMessageConverter"> <constructor-argvalue="UTF-8"/> </bean> <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="com.github.miemiedev.mybatis.paginator.jackson2.PageListJsonMapper"/> </property> </bean> </mvc:message-converters> </mvc:annotation-driven>
那麼在Controller就可以這樣用了:
@ResponseBody@RequestMapping(value ="/findByCity.json")public List findByCity(@RequestParam String city, @RequestParam(required =false,defaultValue ="1") intpage, @RequestParam(required =false,defaultValue ="30") intlimit, @RequestParam(required =false) String sort, @RequestParam(required =false) String dir) { return userService.findByCity(city, newPageBounds(page, limit, Order.create(sort,dir)));}
然後序列化後的JSON字串就會變成這樣的:
{ "items":[ {"NAME":"xiaoma","AGE":30,"GENDER":1,"ID":3,"CITY":"BeiJing"}, {"NAME":"xiaoli","AGE":30,"SCORE":85,"GENDER":1,"ID":1,"CITY":"BeiJing"}, {"NAME":"xiaowang","AGE":30,"SCORE":92,"GENDER":0,"ID":2,"CITY":"BeiJing"}, {"NAME":"xiaoshao","AGE":30,"SCORE":99,"GENDER":0,"ID":4,"CITY":"BeiJing"} ], "slider": [1, 2, 3, 4, 5, 6, 7], "hasPrePage":false, "startRow": 1, "offset": 0, "lastPage":false, "prePage": 1, "hasNextPage":true, "nextPage": 2, "endRow": 30, "totalCount": 40351, "firstPage":true, "totalPages": 1346, "limit": 30, "page": 1}
=========================================
在SpringMVC中使用JSTL的話可以參考一下步驟(懶人用法)
在Spring設定檔中加入攔截器,或則參考攔截器實現定義自己的攔截器
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**"/> <bean class="com.github.miemiedev.mybatis.paginator.springmvc.PageListAttrHandlerInterceptor"/> </mvc:interceptor></mvc:interceptors>
然後Controller方法可以這樣寫
@RequestMapping(value ="/userView.action")public ModelAndView userView(@RequestParam String city, @RequestParam(required =false,defaultValue ="1")intpage, @RequestParam(required =false,defaultValue ="30")intlimit, @RequestParam(required =false) String sort, @RequestParam(required =false) String dir) { List users = userService.findByCity(city,newPageBounds(page, limit, Order.create(sort,dir))); returnnewModelAndView("account/user","users", users);}
JSP中就可以這樣用了,攔截器會將PageList分拆添加Paginator屬性,預設命名規則為"原屬性名稱"+"Paginator"
<table> <c:forEach items="${users}"var="user"> <tr> <td>${user['ID']}</td> <td>${user['NAME']}</td> <td>${user['AGE']}</td> </tr> </c:forEach></table>上一頁: ${usersPaginator.prePage} 當前頁: ${usersPaginator.page} 下一頁: ${usersPaginator.nextPage} 總頁數: ${usersPaginator.totalPages} 總條數: ${usersPaginator.totalCount} 更多屬性參考Paginator類提供的方法
=========================================
如果用如下方法設定pageBounds,當前這個查詢就可以用兩個線程同時查詢list和totalCount了
|
pageBounds.setAsyncTotalCount(true); |
如果所有的分頁查詢都是用非同步方式查詢list和totalCount,可以在外掛程式配置加入asyncTotalCount屬性
<plugin interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor"> <property name="dialectClass" value="com.github.miemiedev.mybatis.paginator.dialect.OracleDialect"/> <property name="asyncTotalCount" value="true"/></plugin>
但是你仍然可以用下面代碼強制讓這個查詢不用非同步
pageBounds.setAsyncTotalCount(false);
當然需要注意的是,只要你用到了非同步查詢,由於裡面使用了線程池,所以在使用時就要加入清理監聽器,以便在停止服務時關閉線程池。需要在web.xml中加入
<listener> <listener-class>com.github.miemiedev.mybatis.paginator.CleanupMybatisPaginatorListener</listener-class></listener>