mybatis-plus 動態表名


mybatis-plus 動態表名

一:背景

 

我們在查詢數據庫設計的時候會按一定的條件分表,我們需要根據條件拼接動態表名

   在動態分表的背景下,有時候查詢數據的時候需要跨表查詢,那此時就需要MP在解析的時候,能夠很好的自適應表格名稱,進行wrapper條件查詢

二:實現

 MP中是通過PaginationInterceptor(分頁插件)完成動態表名解析的,最終用法如下:

 

DynamicTableTreadLocal.INSTANCE.setTableName(GcQmUtil.getCartNumberByCartNumber(cartNumber));
QueryWrapper<QmRectifySlave> wrapper = new QueryWrapper<>();

 

 

 三:pom.xml 依賴

 

        <mybatis-plus-boot-starter.version>3.3.1</mybatis-plus-boot-starter.version>
<!-- mybatis-plus begin -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>${mybatis-plus-boot-starter.version}</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>${mybatis-plus-boot-starter.version}</version>
        </dependency>

 

 

 四:配置類

package com.kexin.common.config;

import com.baomidou.mybatisplus.extension.incrementer.OracleKeyGenerator;
import com.baomidou.mybatisplus.extension.parsers.DynamicTableNameParser;
import com.baomidou.mybatisplus.extension.parsers.ITableNameHandler;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;

import java.util.Collections;
import java.util.HashMap;

@SpringBootConfiguration
@MapperScan("com.kexin.admin.mapper*")
public class MybatisPlusConfig {

    private static final String DYNAMIC_TABLE_PRE = "QM_RECTIFY_SLAVE";
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 設置請求的頁面大於最大頁后操作, true調回到首頁,false 繼續請求  默認false
        // paginationInterceptor.setOverflow(false);
        // 設置最大單頁限制數量,默認 500 條,-1 不受限制
        // paginationInterceptor.setLimit(500);
        // 開啟 count 的 join 優化,只針對部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
//        paginationInterceptor.setDbType("oracle");

        // 設置請求的頁面大於最大頁后操作, true調回到首頁,false 繼續請求  默認false
        paginationInterceptor.setOverflow(false);
        // 設置最大單頁限制數量,默認 500 條,-1 不受限制
        paginationInterceptor.setLimit(500);
//        // 開啟 count 的 join 優化,只針對部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        DynamicTableNameParser dynamicTableNameParser = new DynamicTableNameParser();
        dynamicTableNameParser.setTableNameHandlerMap(new HashMap<String, ITableNameHandler>(2) {{
            //動態表規則-生成自己需要的動態表名
            put(DYNAMIC_TABLE_PRE, (metaObject, sql, tableName) -> DynamicTableTreadLocal.INSTANCE.getTableName());
        }});
        paginationInterceptor.setSqlParserList(Collections.singletonList(dynamicTableNameParser));

        return paginationInterceptor;
    }


    /**
     * Sequence主鍵自增
     *
     * @return 返回oracle自增類
     * @author
     * @date 2019/1/2
     */
    @Bean
    public OracleKeyGenerator oracleKeyGenerator(){
        return new OracleKeyGenerator();
    }
}

 五:動態表名存儲類

 

package com.kexin.common.config;

/**
 * @description: 動態表名存儲類
 * @author: 巫恆強
 * @time: 2021/7/22 10:32
 */
public enum DynamicTableTreadLocal {
    INSTANCE;
    private ThreadLocal<String> tableName = new ThreadLocal<>();

    public String getTableName() {
        return tableName.get();
    }

    public void setTableName(String tableName) {
        this.tableName.set(tableName);
    }

    public void remove() {
        tableName.remove();
    }

}

 

 

 

六:工具類 (根據實際情況編寫)

 

package com.kexin.common.util.gc;


import com.kexin.admin.entity.tables.QmRectifyMaster;

/**
 * @description:
 * @author: 巫恆強
 * @time: 2021/7/15 14:24
 */
public class GcQmUtil {

    public static String getCartNumberByRectifyMater(QmRectifyMaster master){
        return "QM_RECTIFY_SLAVE_"+master.getCartNumber().substring(0,2);
    }
    public static String getCartNumberByCartNumber(String cartNumber){
        return "QM_RECTIFY_SLAVE_"+cartNumber.substring(0,2);
    }
}

 

 

 

 七:具體使用 (分頁動態查詢)

 

 DynamicTableTreadLocal.INSTANCE.setTableName(GcQmUtil.getCartNumberByCartNumber(cartNumber));
        QueryWrapper<QmRectifySlave> wrapper = new QueryWrapper<>();
        wrapper.eq("RECTIFYM_ID",rectifymId);
        IPage<QmRectifySlave> ipage = qmRectifySlaveService.page(new Page<>(page,limit),wrapper);

 

 

八:其他 原理

  1.  以mybatis的query方法作為入口
  2. 通過動態代理執行到配置的分頁插件
  3. 通過分頁插件進行sql解析
  4. 根據分頁插件中配置的tableNameHandler進行目標表格的替換
  5. 最后形成一個可執行sql,執行查詢

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM