Mybatis分頁和Spring的整合

瓜瓜東西發表於2014-09-16

本人用的是第下面例項可通過搜尋獲取個的方式,記得上面寫的少了一部分,一定要加上

   <plugins>
        <plugin interceptor="com.github.miemiedev.mybatis.paginator.OffsetLimitInterceptor">
            <property name="dialectClass" value="com.github.miemiedev.mybatis.paginator.dialect.MySQLDialect"/>
        </plugin>
    </plugins>

例項方式

 

在SpringMVC中使用JSTL的話可以參考一下步驟(懶人用法)

在Spring配置檔案中加入攔截器,或則參考攔截器實現定義自己的攔截器


 

 

 

 

 

寫了一個Mybatis分頁控制元件,在這記錄一下使用方式。

在Maven中加入依賴:

?
1
2
3
4
5
6
7
8
9
<dependencies>
  ...
    <dependency>
        <groupId>com.github.miemiedev</groupId>
        <artifactId>mybatis-paginator</artifactId>
        <version>1.2.15</version>
    </dependency>
 ...
</dependencies>


Mybatis配置檔案新增分頁外掛:

?
1
2
3
4
5
6
7
8
9
10
11
<?xml version="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">
            <property name="dialectClass" value="com.github.miemiedev.mybatis.paginator.dialect.OracleDialect"/>
        </plugin>
    </plugins>
</configuration>


建立一個查詢,內容可以是任何Mybatis表示式,包括foreach和if等:

?
1
2
3
<select id="findByCity" resultType="map">
    select * from TEST_USER where city = #{city};
</select>


Dao中的方法或許是這樣(用介面也是類似):

?
1
2
3
4
5
6
7
public List findByCity(String city, PageBounds pageBounds){
 
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("city",city);
 
    return getSqlSession().selectList("db.table.user.findByCity", params, pageBounds);
}


呼叫方式(分頁加多列排序):

?
1
2
3
4
5
6
7
8
9
int page = 1//頁號
int pageSize = 20//每頁資料條數
String sortString = "age.asc,gender.desc";//如果你想排序的話逗號分隔可以排序多列
PageBounds pageBounds = new PageBounds(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這個物件來控制結果的輸出,常用的使用方式一般都可以通過建構函式來配置。

?
1
2
3
4
5
6
7
new PageBounds();//預設建構函式不提供分頁,返回ArrayList
new PageBounds(int limit);//取TOPN操作,返回ArrayList
new PageBounds(Order... order);//只排序不分頁,返回ArrayList
 
new PageBounds(int page, int limit);//預設分頁,返回PageList
new PageBounds(int page, int limit, Order... order);//分頁加排序,返回PageList
new PageBounds(int page, int limit, List<Order> orders, boolean containsTotalCount);//使用containsTotalCount來決定查不查詢totalCount,即返回ArrayList還是PageList


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

如果用的是Spring MVC的話可以把JSON的配置寫成這樣:

?
1
2
3
4
5
6
7
8
9
10
11
12
<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        <bean class="org.springframework.http.converter.StringHttpMessageConverter"
            <constructor-arg value="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就可以這樣用了:

?
1
2
3
4
5
6
7
8
9
@ResponseBody
@RequestMapping(value = "/findByCity.json")
public List findByCity(@RequestParam String city,
                 @RequestParam(required = false,defaultValue = "1"int page,
                 @RequestParam(required = false,defaultValue = "30"int limit,
                 @RequestParam(required = false) String sort,
                 @RequestParam(required = false) String dir) {
    return userService.findByCity(city, new PageBounds(page, limit, Order.create(sort,dir)));
}


然後序列化後的JSON字串就會變成這樣的:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "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配置檔案中加入攔截器,或則參考攔截器實現定義自己的攔截器

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

然後Controller方法可以這樣寫

?
1
2
3
4
5
6
7
8
9
@RequestMapping(value = "/userView.action")
public ModelAndView userView(@RequestParam String city,
                 @RequestParam(required = false,defaultValue = "1"int page,
                 @RequestParam(required = false,defaultValue = "30"int limit,
                 @RequestParam(required = false) String sort,
                 @RequestParam(required = false) String dir) {
    List users = userService.findByCity(city, new PageBounds(page, limit, Order.create(sort,dir)));
    return new ModelAndView("account/user","users", users);
}

JSP中就可以這樣用了,攔截器會將PageList分拆新增Paginator屬性,預設命名規則為"原屬性名稱"+"Paginator"

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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

?
1
pageBounds.setAsyncTotalCount(true);

如果所有的分頁查詢都是用非同步的方式查詢list和totalCount,可以在外掛配置加入asyncTotalCount屬性

?
1
2
3
4
<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>

但是你仍然可以用下面程式碼強制讓這個查詢不用非同步

?
1
pageBounds.setAsyncTotalCount(false);

當然需要注意的是,只要你用到了非同步查詢,由於裡面使用了執行緒池,所以在使用時就要加入清理監聽器,以便在停止服務時關閉執行緒池。需要在web.xml中加入

?
1
2
3
<listener>
    <listener-class>com.github.miemiedev.mybatis.paginator.CleanupMybatisPaginatorListener</listener-class>
</listener>


完。

 

 

 

 

 

相關文章