Mybatis分頁查詢SQL詳解

一、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分頁插件進行分頁查詢非常簡單,只需要按照以下步驟配置即可:

  1. 在mybatis-config.xml中添加插件:
  2. <plugins>
       <plugin interceptor="com.example.PageInterceptor"></plugin>
    </plugins>
    
  3. 在Mapper.xml中添加分頁SQL語句:
  4. <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>
    
  5. 在Java代碼中調用分頁查詢方法:
  6. 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分頁插件源碼解析可以深入理解其實現原理和機制,這裡只簡要介紹:

    1. Mybatis分頁插件主要實現了Intercepter介面和Invocation介面,其中Intercepter介面用來對SQL語句進行攔截和修改,Invocation介面則用來執行真正的SQL語句和返回結果。
    2. Mybatis分頁插件使用了ThreadLocal類來將分頁參數綁定到當前線程中,避免了多線程並發訪問時的參數混淆問題。
    3. Mybatis分頁插件實現了自定義註解、Mapper介面和XML映射文件的自動綁定機制,可以大大減少開發工作量。

    六、Mybatis分頁查詢注意事項

    使用Mybatis分頁插件進行分頁查詢需要注意以下事項:

    1. 分頁參數必須是一個Java對象,並且至少包含起始行數和每頁數量兩個屬性。
    2. 分頁參數必須綁定到Mapper介面的方法參數中。
    3. 分頁查詢SQL語句必須以limit為結尾。
    4. 分頁插件使用了反射機制和強制類型轉換,請注意避免出現類型轉換異常。

    七、總結

    Mybatis分頁查詢是非常重要的功能,可以大大提高查詢效率和降低內存消耗。可以通過Mybatis分頁插件進行快速、簡便的實現,並根據需要進行一定的自定義修改。

    原創文章,作者:QPOIO,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/371731.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
QPOIO的頭像QPOIO
上一篇 2025-04-23 18:08
下一篇 2025-04-23 18:08

相關推薦

  • Hibernate日誌列印sql參數

    本文將從多個方面介紹如何在Hibernate中列印SQL參數。Hibernate作為一種ORM框架,可以通過列印SQL參數方便開發者調試和優化Hibernate應用。 一、通過配置…

    編程 2025-04-29
  • jQuery Datatable分頁中文

    jQuery Datatable是一個非常流行的數據表插件,它可以幫助您快速地在頁面上創建搜索、過濾、排序和分頁的數據表格。不過,它的默認設置是英文的,今天我們就來探討如何將jQu…

    編程 2025-04-29
  • 使用SQL實現select 聚合查詢結果前加序號

    select語句是資料庫中最基礎的命令之一,用於從一個或多個表中檢索數據。常見的聚合函數有:count、sum、avg等。有時候我們需要在查詢結果的前面加上序號,可以使用以下兩種方…

    編程 2025-04-29
  • 理解Mybatis中的SQL Limit用法

    Mybatis是一種非常流行的ORM框架,提供了SQL映射配置文件,可以使用類似於傳統SQL語言的方式編寫SQL語句。其中,SQL的Limit語法是一個非常重要的知識點,能夠實現分…

    編程 2025-04-29
  • SQL預研

    SQL預研是指在進行SQL相關操作前,通過數據分析和理解,確定操作的方法和步驟,從而避免不必要的錯誤和問題。以下從多個角度進行詳細闡述。 一、數據分析 數據分析是SQL預研的第一步…

    編程 2025-04-28
  • uniapp分頁第二次請求用法介紹

    本文將從多個方面對uniapp分頁第二次請求進行詳細闡述,並給出對應的代碼示例。 一、請求參數的構造 在進行分頁請求時,需要傳遞的參數體包含當前頁碼以及每頁顯示的數據量。對於第二次…

    編程 2025-04-27
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁碟中。在執行sync之前,所有的文件系統更新將不會立即寫入磁碟,而是先緩存在內存…

    編程 2025-04-25
  • 神經網路代碼詳解

    神經網路作為一種人工智慧技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網路的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網路模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web伺服器。nginx是一個高性能的反向代理web伺服器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25

發表回復

登錄後才能評論