Mybatis分頁外掛——PageHelper使用與原理介紹
推薦一款Mybatis分頁外掛
以前也寫過一篇博文介紹Mybatis的外掛,以及如何通過Mybatis的外掛功能實現一個自定義的分頁外掛,但是那個外掛的侵入性是比較大的。前段時間遇到了一款開源的Mybatis分頁外掛,叫PageHelper
,github地址是https://github.com/pagehelper/Mybatis-PageHelper,其原理是通過ThreadLocal
來存放分頁資訊,從而可以做到在Service層實現無侵入性的Mybatis分頁實現。筆者感覺還不錯,所以特意發博文記錄一下,並推薦給大家。
簡單示例
以下是使用PageHelper
進行分頁的一個簡單的示例,更多詳細的內容,請大家引數上面提供的github地址。
新增依賴
筆者使用的是Maven,新增依賴如下。
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>4.1.6</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
註冊Mybatis Plugin
跟其它Mybatis Plugin一樣,我們需要在Mybatis的配置檔案中註冊需要使用的Plugin,PageHelper
com.github.pagehelper.PageHelper
自身。順便說一句,Mybatis的Plugin我們說是Plugin,實際上對應的卻是org.apache.ibatis.plugin.Interceptor
介面,因為Interceptor
的核心是其中的plugin(Object target)
方法,而對於plugin(Object target)
方法的實現,我們在需要對對應的物件進行攔截時會通過org.apache.ibatis.plugin.Plugin
的靜態方法wrap(Object target, Interceptor interceptor)
Interceptor
實現類。
<plugins>
<plugin interceptor="com.github.pagehelper.PageHelper"/>
</plugins>
- 1
- 2
- 3
使用PageHelper
PageHelper
攔截的是org.apache.ibatis.executor.Executor
的query
方法,其傳參的核心原理是通過ThreadLocal
進行的。當我們需要對某個查詢進行分頁查詢時,我們可以在呼叫Mapper進行查詢前呼叫一次PageHelper.startPage(..)
,這樣PageHelper
會把分頁資訊存入一個ThreadLocal
變數中。在攔截到Executor
的query
方法執行時會從對應的ThreadLocal
中獲取分頁資訊,獲取到了,則進行分頁處理,處理完了後又會把ThreadLocal
中的分頁資訊清理掉,以便不影響下一次的查詢操作。所以當我們使用了PageHelper.startPage(..)
後,每次將對最近一次的查詢進行分頁查詢,如果下一次查詢還需要進行分頁查詢,需要重新進行一次PageHelper.startPage(..)
。這樣就做到了在引入了分頁後可以對原來的查詢程式碼沒有任何的侵入性。此外,在進行分頁查詢時,我們的返回結果一般是一個java.util.List
,PageHelper
分頁查詢後的結果會變成com.github.pagehelper.Page
型別,其繼承了java.util.ArrayList
,所以不會對我們的方法宣告造成影響。com.github.pagehelper.Page
中包含有返回結果的分頁資訊,包括總記錄數,總的分頁數等資訊,所以一般我們需要把返回結果強轉為com.github.pagehelper.Page
型別。以下是一個簡單的使用PageHelper
進行分頁查詢的示例程式碼。
public class PageHelperTest {
private static SqlSessionFactory sqlSessionFactory;
private SqlSession session;
@BeforeClass
public static void beforeClass() throws IOException {
InputStream is = Resources.getResourceAsStream("mybatis-config-single.xml");
sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
}
@Before
public void before() {
this.session = sqlSessionFactory.openSession();
}
@After
public void after() {
this.session.close();
}
@Test
public void test() {
int pageNum = 2;//頁碼,從1開始
int pageSize = 10;//每頁記錄數
PageHelper.startPage(pageNum, pageSize);//指定開始分頁
UserMapper userMapper = this.session.getMapper(UserMapper.class);
List<User> all = userMapper.findAll();
Page<User> page = (Page<User>) all;
System.out.println(page.getPages());
System.out.println(page);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
以上是通過PageHelper.startPage(..)
傳遞分頁資訊的示例,其實PageHelper
還支援Mapper引數傳遞分頁資訊等其它用法。關於PageHelper
的更多用法和配置資訊等請參考該專案的GitHub官方文件。
(本文由Elim寫於2017年5月31日)