Springboot+Mybatis+Mybatisplus 框架中增加自定義分頁外掛和sql 預留位置修改外掛

2023-10-27 21:00:53

一、Springboot簡介

springboot 是當下最流行的web 框架,Spring Boot是由Pivotal團隊提供的全新框架,其設計目的是用來簡化新Spring應用的初始搭建以及開發過程。該框架使用了特定的方式來進行設定,從而使開發人員不再需要定義樣板化的設定,讓這些框架整合在一起變得更加簡單,簡化了我們在整合過程中繁瑣的模板化設定,springboot的核心特點如下:

1. 獨立執行:SpringBoot開發的應用可以以JRA包的形式獨立執行,執行一個SpringBoot應用只需通過 java –jar xxxx.jar 來執行;

2. 內嵌容器:SpringBoot內嵌了多個WEB容器,如:Tomcat、Jetty、Undertow,所以可以使用非WAR包形式進行專案部署;

3. 自動starter依賴:SpringBoot提供了一系列的starter來簡化Maven的依賴載入。starter是一組方便的依賴關係描述符,它將常用的依賴分組並將其合併到一個依賴中,這樣就可以一次性將相關依賴新增到Maven或Gradle中;

4. 自動設定:SpringBoot會根據在類路徑中的JAR包和類,自動將類注入到SpringBoot的上下文中,極大地減少設定的使用;

5. 應用監控:SpringBoot提供基於http、ssh、telnet的監控方式,對執行時的專案提供生產級別的服務監控和健康檢測;

6. 無程式碼生成/無需編寫XML設定:SpringBoot不是藉助於程式碼生成來實現的,而是通過條件註解來實現的,這是 Spring 4.x 提供的新特性。Spring4.x提倡使用Java設定和註解組合,無需編寫任何xml設定即可實現Spring的所有設定功能;

二、Mybatis和Mybatisplus 簡介

MyBatis 是支援普通 SQL查詢,儲存過程和高階對映的優秀持久層框架。MyBatis 消除了幾乎所有的JDBC程式碼和引數的手工設定以及結果集的檢索。MyBatis 使用簡單的 XML或註解用於設定和原始對映,將介面和 Java 的POJOs(Plain Ordinary Java Objects,普通的 Java物件)對映成資料庫中的記錄。
每個MyBatis應用程式主要都是使用SqlSessionFactory範例的,一個SqlSessionFactory範例可以通過SqlSessionFactoryBuilder獲得。SqlSessionFactoryBuilder可以從一個xml組態檔或者一個預定義的設定類的範例獲得。
用xml檔案構建SqlSessionFactory範例是非常簡單的事情。推薦在這個設定中使用類路徑資源(classpath resource),但你可以使用任何Reader範例,包括用檔案路徑或file://開頭的url建立的範例。MyBatis有一個實用類----Resources,它有很多方法,可以方便地從類路徑及其它位置載入資源。

MyBatis中文網站:https://mybatis.net.cn/

MyBatis blog:https://blog.mybatis.org/

MyBatis 官方網站:https://mybatis.org/mybatis-3/

MyBatis github:https://github.com/mybatis/mybatis-3

MyBatis-Plus(簡稱 MP)是一個 MyBatis 的增強工具,在 MyBatis 的基礎上只做增強不做改變,為簡化開發、提高效率而出現的框架,它對 Mybatis 的基礎功能進行了增強,但未做任何改變。

MyBatis-Plus官網:https://baomidou.com/

MyBatis-Plus github:https://github.com/baomidou/mybatis-plus

三、Springboot+Mybatis+Mybatisplus 框架中增加自定義分頁外掛和sql 預留位置修改外掛

1、如何自定義分頁外掛

1)、在MyBatis-Plus 提供了com.baomidou.mybatisplus.extension.plugins.pagination.dialects.IDialect的介面抽象,如果需要自定義一個分頁外掛,需要先實現該介面,

public class MyDialect implements IDialect {

    @Override
    public MyDialect buildPaginationSql(String originalSql, long offset, long limit) {
        //範例
        limit = (offset >= 1) ? (offset + limit) : limit;
        String sql = "SELECT * FROM ( SELECT TMP.*, ROW_NUMBER() OVER (ORDER BY 0) ROW_ID FROM ( " +
                originalSql + " ) TMP LIMIT " + FIRST_MARK + ") WHERE ROW_ID > " + SECOND_MARK;
        return new MyDialect(sql, limit, offset).setConsumerChain();
    }
}

2)、實現由MyBatis-Plus 提供的com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor 介面

public class CustomerPaginationInnerInterceptor extends PaginationInnerInterceptor {


    @Override
    protected IDialect findIDialect(Executor executor) {
        return new MyDialect(); //這裡也可以自己增加判斷,根據不同的資料庫型別,使用不同的IDialect 實現
    }
}

2、如何自定義sql 預留位置修改外掛

需要實現MyBatis-Plus 提供的com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor提供的介面,在mybatis-plus中,提供了innerinterceptor攔截器,可以方便地實現拼接查詢條件。 innerinterceptor攔截器可以攔截所有的select語句,然後可以對攔截到的sql語句做修改。

public class MyReplacePlaceholderInnerInterceptor implements InnerInterceptor {

    public MyReplacePlaceholderInnerInterceptor() {

    }

    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        String sql = boundSql.getSql();
         //TODO 對SQL 語句做預留位置的替換
            PluginUtils.mpBoundSql(boundSql).sql(sql);
    }
}

 3、定義自定義的mybatis的Configuration設定

@Configuration
public class MybatisPlusConfiguration implements InitializingBean {

    @Autowired
    private MybatisPlusInterceptor mybatisPlusInterceptor;

    @Override
    public void afterPropertiesSet() throws Exception {
        
        List<InnerInterceptor> targetInterceptors = new ArrayList<>();
        MyReplacePlaceholderInnerInterceptor  myPlaceholderInnerInterceptor = new MyReplacePlaceholderInnerInterceptor ();
        targetInterceptors.add(myPlaceholderInnerInterceptor);
        // 先執行MybatisCustomerInterceptor
        List<InnerInterceptor> interceptors = mybatisPlusInterceptor.getInterceptors();
        interceptors.forEach(innerInterceptor -> {
            if (innerInterceptor instanceof PaginationInnerInterceptor) {
                // 自定義分頁外掛
                CustomerPaginationInnerInterceptor customerPaginationInnerInterceptor = new CustomerPaginationInnerInterceptor();
                customerPaginationInnerInterceptor.setMaxLimit(1000L);
                targetInterceptors.add(customerPaginationInnerInterceptor);
            }
            else {
                targetInterceptors.add(innerInterceptor);
            }
        });
        mybatisPlusInterceptor.setInterceptors(targetInterceptors);
    }
}