一、Mybatis分頁查詢介紹
Mybatis是一款優秀的持久層框架,支持動態SQL和參數映射等功能,而分頁查詢也是其中非常重要的功能之一。
分頁查詢是指將大量的數據按照需要的記錄數分為多個頁面展示,適用於大型數據查詢和數據展示。
二、Mybatis分頁查詢實現
Mybatis分頁查詢可以通過SQL語句的limit關鍵字實現,不同的數據庫語法略有不同,下面是兩種常見的方式:
mysql:SELECT * FROM table LIMIT 0, 10; oracle:SELECT * FROM (SELECT a.*, ROWNUM rn FROM table a WHERE ROWNUM = 0;
MySQL使用”limit start,pageSize”來實現分頁,其中start為起始行數,pageSize為每頁數量。而Oracle則需要使用子查詢和ROWNUM來實現相同的效果。
但是,這種方式並不是最優的分頁查詢方式,因為它會先查詢所有數據,然後再根據指定的起始行數和數量來返回結果集。同時又因為Mybatis是懶加載的,只有在調用結果集時才會產生真正的SQL查詢,所以需要改進這種實現方式。
三、Mybatis分頁插件介紹
Mybatis分頁插件可以屏蔽底層的分頁SQL,通過攔截StatementHandler接口的prepare方法,實現物理分頁,減少查詢不必要的數據傳輸和內存消耗,提高查詢效率。
下面是Mybatis分頁插件的示例代碼:
public class PageInterceptor implements Interceptor {
private static final ThreadLocal LOCAL_PAGE = new ThreadLocal();
/**
* 插件實現方法
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 獲取當前真正執行的SQL語句
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
String sqlId = mappedStatement.getId();
BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
// 只攔截需要分頁的SQL語句
if (isPageSql(sqlId)) {
Object parameterObject = boundSql.getParameterObject();
Page page = null;
// 獲取分頁參數
if (parameterObject instanceof Page) {
page = (Page) parameterObject;
} else if (parameterObject instanceof Map) {
for (Object arg : ((Map) parameterObject).values()) {
if (arg instanceof Page) {
page = (Page) arg;
break;
}
}
}
if (page == null) {
throw new IllegalArgumentException("Page parameter not found");
}
// 修改SQL語句
String sql = boundSql.getSql();
String newSql = sql + " limit " + page.getStart() + "," + page.getPageSize();
ReflectUtil.setFieldValue(boundSql, "sql", newSql);
LOCAL_PAGE.set(page);
}
// 執行原SQL
Object result = invocation.proceed();
if (LOCAL_PAGE.get() != null) {
// 封裝查詢結果
PageList pageList = new PageList((List) result, LOCAL_PAGE.get());
LOCAL_PAGE.remove();
return pageList;
}
return result;
}
/**
* 是否是分頁SQL
*/
private boolean isPageSql(String sqlId) {
return sqlId.matches(".+Page$")
|| sqlId.matches(".+PageX$")
|| sqlId.matches(".+PageX?[0-9]*$");
}
// 省略其他代碼
}
這裡使用了ThreadLocal類來將分頁參數綁定到當前線程中,在分頁參數封裝後再進行返回。主要使用了ReflectUtil.setFieldValue()方法修改BoundSql中的SQL語句。
四、Mybatis分頁查詢使用方法
使用Mybatis分頁插件進行分頁查詢非常簡單,只需要按照以下步驟配置即可:
- 在mybatis-config.xml中添加插件:
- 在Mapper.xml中添加分頁SQL語句:
- 在Java代碼中調用分頁查詢方法:
- Mybatis分頁插件主要實現了Intercepter接口和Invocation接口,其中Intercepter接口用來對SQL語句進行攔截和修改,Invocation接口則用來執行真正的SQL語句和返回結果。
- Mybatis分頁插件使用了ThreadLocal類來將分頁參數綁定到當前線程中,避免了多線程並發訪問時的參數混淆問題。
- Mybatis分頁插件實現了自定義註解、Mapper接口和XML映射文件的自動綁定機制,可以大大減少開發工作量。
- 分頁參數必須是一個Java對象,並且至少包含起始行數和每頁數量兩個屬性。
- 分頁參數必須綁定到Mapper接口的方法參數中。
- 分頁查詢SQL語句必須以limit為結尾。
- 分頁插件使用了反射機制和強制類型轉換,請注意避免出現類型轉換異常。
<plugins> <plugin interceptor="com.example.PageInterceptor"></plugin> </plugins>
<select id="findUserPage" parameterType="map" resultType="com.example.User">
select * from user where 1=1
<if test="username != null"> and username like '%${username}%</if>
<if test="age != null"> and age = #{age}</if>
<if test="gender != null"> and gender = #{gender}</if>
limit #{page.start},#{page.pageSize}
</select>
Page page = new Page(1, 10);
Map param = new HashMap();
param.put("username", "test");
param.put("age", 18);
param.put("gender", 1);
param.put("page", page);
List userList = userDao.findUserPage(param);
其中,Page是分頁參數封裝類,包含起始行數和每頁數量兩個屬性。
五、Mybatis分頁插件源碼解析
Mybatis分頁插件源碼解析可以深入理解其實現原理和機制,這裡只簡要介紹:
六、Mybatis分頁查詢注意事項
使用Mybatis分頁插件進行分頁查詢需要注意以下事項:
七、總結
Mybatis分頁查詢是非常重要的功能,可以大大提高查詢效率和降低內存消耗。可以通過Mybatis分頁插件進行快速、簡便的實現,並根據需要進行一定的自定義修改。
原創文章,作者:QPOIO,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/371731.html
微信掃一掃
支付寶掃一掃