首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

SpringMVC 整合 MyBatis 實現通用分頁插件完整實作

     編輯:Java 相關知識

基於 MyBatis 攔截器機制的分頁插件實現

本文詳細介紹如何在 SpringMVC + MyBatis 架構下,利用 MyBatis 的攔截器機制實現一個通用的分頁插件,支援 MySQL 和 Oracle 等主流資料庫方言。

1. 封裝分頁實體類

首先定義分頁介面 IPage 與基礎實現 BasePage,包含頁碼、頁大小、總筆數、總頁數等核心屬性,並提供首頁、尾頁、上一頁、下一頁等判斷方法:

public abstract class BasePage implements IPage, Serializable {
    public static int DEFAULT_PAGE_SIZE = 20;
    private int pageSize = DEFAULT_PAGE_SIZE;
    private int currentPage = 1;
    private int totalCount = -1;
    
    // 核心計算方法
    public int getFirstResult() { return (this.currentPage - 1) * this.pageSize; }
    public int getTotalPage() { /* 計算總頁數邏輯 */ }
    public boolean isFirstPage() { return this.currentPage <= 1; }
    public boolean isLastPage() { return this.currentPage >= getTotalPage(); }
    // ... 其他 getter/setter
}

public class Page extends BasePage {
    private List data;
    public static ThreadLocal threadLocal = new ThreadLocal<>();
    // 建構子與資料存取方法
}

2. 實現 MyBatis 分頁攔截器

核心類 PagePlugin 實作 Interceptor 介面,攔截 StatementHandler.prepare 方法:

@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class }) })
public class PagePlugin implements Interceptor {
    private String dialect = "";
    private String pageSqlId = "";

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 獲取 RoutingStatementHandler 與 MappedStatement
        // 從 ThreadLocal 取得 Page 物件
        // 針對符合 pageSqlId 規則的查詢進行分頁處理
        // 執行 COUNT 查詢獲取總筆數
        // 根據方言生成分頁 SQL (MySQL LIMIT / Oracle ROWNUM)
        // 修改 BoundSql 中的 SQL 為分頁 SQL
        return invocation.proceed();
    }

    private String generatePageSql(String sql, Page page) {
        if ("mysql".equals(dialect)) {
            return sql + " LIMIT " + page.getCurrentResult() + "," + page.getPageSize();
        } else if ("oracle".equals(dialect)) {
            // Oracle 雙層巢狀 ROWNUM 分頁寫法
        }
        return sql;
    }
    // 參數設值、屬性配置等輔助方法
}

3. MyBatis 設定檔配置

在 mybatis-config.xml 中註冊攔截器:

<configuration>
    <plugins>
        <plugin interceptor="com.framework.common.page.plugin.PagePlugin">
            <property name="dialect" value="mysql" />
            <property name="pageSqlId" value="ByPage" />
        </plugin>
    </plugins>
</configuration>

規約:需分頁的查詢語句 ID 必須以 ByPage 結尾,對應的計數查詢 ID 為將 ByPage 替換為 Count。

4. Spring MVC 攔截器自動綁定分頁參數

PageInterceptor 繼承 HandlerInterceptorAdapter,在 preHandle 中從請求參數讀取 pageNo、pageSize 建立 Page 物件存入 ThreadLocal,在 postHandle 中將分頁結果放入請求屬性並清理 ThreadLocal:

public class PageInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        Page page = new Page();
        String pageSize = request.getParameter("pageSize");
        String pageNo = request.getParameter("pageNo");
        if (NumberUtils.isNumber(pageSize)) page.setPageSize(NumberUtils.toInt(pageSize));
        if (NumberUtils.isNumber(pageNo)) page.setPageNo(NumberUtils.toInt(pageNo));
        Page.threadLocal.set(page);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        Page page = Page.threadLocal.get();
        if (page != null) request.setAttribute("page", page);
        Page.threadLocal.remove();
    }
}

5. Spring 整合配置

配置 SqlSessionFactoryBean 載入 MyBatis 設定檔、掃描 Mapper 接口,並註冊 PageInterceptor 到 RequestMappingHandlerMapping:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="classpath:mybatis-config.xml" />
    <property name="mapperLocations">
        <list><value>classpath:/com/framework/mapper/**/*Mapper.xml</value></list>
    </property>
</bean>

<bean id="pageInterceptor" class="com.framework.common.page.interceptor.PageInterceptor"></bean>
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
    <property name="interceptors"><list><ref bean="pageInterceptor" /></list></property>
</bean>

使用方式

在 Mapper XML 中定義以 ByPage 結尾的查詢語句,對應的 Count 查詢可選(若無則自動包裝 SELECT COUNT(1) FROM (...) T_COUNT)。Controller 方法直接接收 pageNo、pageSize 參數,查詢結果自動包含分頁資訊。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved