最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring Boot集成MyBatis-Plus 自定義攔截器實(shí)現(xiàn)動(dòng)態(tài)表名切換功能

 更新時(shí)間:2024年11月27日 10:20:25   作者:LOVE_DDZ  
本文介紹了如何在SpringBoot項(xiàng)目中集成MyBatis-Plus,并通過(guò)自定義攔截器實(shí)現(xiàn)動(dòng)態(tài)表名切換,此外,還探討了MyBatis攔截器在其他場(chǎng)景中的應(yīng)用,如SQL日志記錄、多租戶(hù)數(shù)據(jù)隔離、數(shù)據(jù)權(quán)限控制等,感興趣的朋友跟隨小編一起看看吧

Spring Boot集成MyBatis-Plus:自定義攔截器實(shí)現(xiàn)動(dòng)態(tài)表名切換

一、引言

介紹動(dòng)態(tài)表名的場(chǎng)景需求,比如多租戶(hù)系統(tǒng)、分表分庫(kù),或者不同業(yè)務(wù)模塊共用一套代碼但操作不同表。說(shuō)明 MyBatis-Plus 默認(rèn)綁定固定表名的問(wèn)題。

二、項(xiàng)目配置

1. 集成 MyBatis-Plus

簡(jiǎn)單說(shuō)明如何在 Spring Boot 中引入 MyBatis-Plus 并配置。

2. 依賴(lài)添加

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>最新版本號(hào)</version>
</dependency>

三、自定義攔截器實(shí)現(xiàn)動(dòng)態(tài)表名

1. 攔截器原理

解釋 MyBatis 攔截器的核心概念,介紹 Interceptor 接口和 @Signature 注解。

2. 攔截器實(shí)現(xiàn)代碼

詳細(xì)展示攔截器的完整實(shí)現(xiàn):

@Component
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class DynamicTableInterceptor implements Interceptor {
  	/**
     * 使用ThreadLocal來(lái)存儲(chǔ)線程特有的數(shù)據(jù),這里用于存儲(chǔ)動(dòng)態(tài)表名
     */
    private static final ThreadLocal<String> TABLE_NAME_HOLDER = new ThreadLocal<>();
    /**
     * 設(shè)置動(dòng)態(tài)表名
     *
     * @param tableName 需要設(shè)置的表名,由調(diào)用者指定
     *                  此方法允許在運(yùn)行時(shí)動(dòng)態(tài)地設(shè)置數(shù)據(jù)庫(kù)表名,以便在多數(shù)據(jù)源或動(dòng)態(tài)表名的場(chǎng)景下靈活地切換表
     */
    public static void setDynamicTableName(String tableName) {
        TABLE_NAME_HOLDER.set(tableName);
    }
    /**
     * 清除當(dāng)前線程中的動(dòng)態(tài)表名
     * 此方法用于清除ThreadLocal中存儲(chǔ)的表名信息,以避免內(nèi)存泄漏
     * 它應(yīng)在每次使用動(dòng)態(tài)表名后調(diào)用,確保不會(huì)對(duì)后續(xù)的請(qǐng)求產(chǎn)生影響
     */
    public static void clearDynamicTableName() {
        TABLE_NAME_HOLDER.remove();
    }
    /**
     * 攔截器
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler handler = (StatementHandler) invocation.getTarget();
        BoundSql boundSql = handler.getBoundSql();
        String tableName = TABLE_NAME_HOLDER.get();
        if (tableName != null) {
            /**
             * 從實(shí)體類(lèi)的@tableName中獲取表名,必須在實(shí)體類(lèi)上面添加@tableName注解
             * 實(shí)體類(lèi)中的@tableName注解中的值,必須是數(shù)據(jù)庫(kù)中的表名,否則會(huì)報(bào)錯(cuò)
             * 例如 :@TableName("t_user_"),數(shù)據(jù)庫(kù)是根據(jù)月份來(lái)的,在這里替換則需要根據(jù)當(dāng)前月份進(jìn)行拼接表名
             */
            Class<?> entityType = boundSql.getParameterObject().getClass();
            String oldTableName = entityType.getAnnotation(TableName.class).value();
            String newSql = boundSql.getSql().replace(oldTableName, tableName);
            Field sqlField = boundSql.getClass().getDeclaredField("sql");
            sqlField.setAccessible(true);
            sqlField.set(boundSql, newSql);
        }
        return invocation.proceed();
    }
}

3. 使用攔截器動(dòng)態(tài)設(shè)置表名

DynamicTableInterceptor.setDynamicTableName("your_dynamic_table_name");
try {
    myService.saveOrUpdateBatch(entities); // MyBatis-Plus 操作
} finally {
    DynamicTableInterceptor.clearDynamicTableName();
}

四、其他場(chǎng)景

MyBatis 攔截器(Interceptor)是 MyBatis 提供的強(qiáng)大擴(kuò)展機(jī)制,可以攔截執(zhí)行過(guò)程中的不同階段并進(jìn)行自定義操作。除了動(dòng)態(tài)修改表名之外,攔截器還可以應(yīng)用于以下多種場(chǎng)景:

1. SQL 日志記錄與審計(jì)

  • 場(chǎng)景:記錄每次執(zhí)行的 SQL 語(yǔ)句、參數(shù)、執(zhí)行時(shí)間等信息。
  • 用途:用于 SQL 審計(jì)、性能監(jiān)控、問(wèn)題排查。

示例

@Override
public Object intercept(Invocation invocation) throws Throwable {
    StatementHandler handler = (StatementHandler) invocation.getTarget();
    BoundSql boundSql = handler.getBoundSql();
    long startTime = System.currentTimeMillis();
    Object result = invocation.proceed();
    long endTime = System.currentTimeMillis();
    System.out.println("SQL: " + boundSql.getSql() + " Execution Time: " + (endTime - startTime) + "ms");
    return result;
}

2. 多租戶(hù)數(shù)據(jù)隔離

  • 場(chǎng)景:根據(jù)當(dāng)前租戶(hù)信息自動(dòng)添加過(guò)濾條件,確保數(shù)據(jù)隔離。
  • 用途:實(shí)現(xiàn) SaaS 系統(tǒng)中不同租戶(hù)的數(shù)據(jù)訪問(wèn)控制。

示例

@Override
public Object intercept(Invocation invocation) throws Throwable {
    StatementHandler handler = (StatementHandler) invocation.getTarget();
    BoundSql boundSql = handler.getBoundSql();
    String originalSql = boundSql.getSql();
    String tenantId = TenantContext.getCurrentTenantId();
    String modifiedSql = originalSql + " WHERE tenant_id = " + tenantId;
    Field sqlField = boundSql.getClass().getDeclaredField("sql");
    sqlField.setAccessible(true);
    sqlField.set(boundSql, modifiedSql);
    return invocation.proceed();
}

3. SQL 參數(shù)加密與解密

  • 場(chǎng)景:對(duì)敏感數(shù)據(jù)(如身份證號(hào)、電話等)在 SQL 操作時(shí)進(jìn)行自動(dòng)加密或解密。
  • 用途:提高數(shù)據(jù)安全性,確保數(shù)據(jù)存儲(chǔ)符合安全規(guī)范。

示例

@Override
public Object intercept(Invocation invocation) throws Throwable {
    StatementHandler handler = (StatementHandler) invocation.getTarget();
    BoundSql boundSql = handler.getBoundSql();
    String sql = boundSql.getSql();
    // 自定義加密邏輯
    // 加密處理參數(shù)
    return invocation.proceed();
}

4. 自動(dòng)分頁(yè)處理

  • 場(chǎng)景:在執(zhí)行查詢(xún)時(shí)自動(dòng)添加分頁(yè)邏輯,避免手動(dòng)分頁(yè)處理。
  • 用途:簡(jiǎn)化分頁(yè)查詢(xún)的代碼。

示例

@Override
public Object intercept(Invocation invocation) throws Throwable {
    StatementHandler handler = (StatementHandler) invocation.getTarget();
    BoundSql boundSql = handler.getBoundSql();
    String originalSql = boundSql.getSql();
    String paginatedSql = originalSql + " LIMIT " + offset + ", " + limit;
    Field sqlField = boundSql.getClass().getDeclaredField("sql");
    sqlField.setAccessible(true);
    sqlField.set(boundSql, paginatedSql);
    return invocation.proceed();
}

5. 數(shù)據(jù)權(quán)限控制

  • 場(chǎng)景:根據(jù)用戶(hù)角色或權(quán)限,自動(dòng)添加數(shù)據(jù)過(guò)濾條件。
  • 用途:確保用戶(hù)只能訪問(wèn)被授權(quán)的數(shù)據(jù)。

示例

@Override
public Object intercept(Invocation invocation) throws Throwable {
    StatementHandler handler = (StatementHandler) invocation.getTarget();
    BoundSql boundSql = handler.getBoundSql();
    String originalSql = boundSql.getSql();
    String userRole = SecurityContext.getCurrentUserRole();
    String restrictedSql = originalSql + " AND role = '" + userRole + "'";
    // 動(dòng)態(tài)修改 SQL
    return invocation.proceed();
}

6. 緩存增強(qiáng)

  • 場(chǎng)景:自定義緩存邏輯,攔截查詢(xún)請(qǐng)求,先檢查緩存是否命中。
  • 用途:減少數(shù)據(jù)庫(kù)訪問(wèn)次數(shù),提高性能。

示例

@Override
public Object intercept(Invocation invocation) throws Throwable {
    // 檢查緩存
    Object cachedResult = CacheManager.get(boundSql.getSql());
    if (cachedResult != null) {
        return cachedResult;
    }
    // 如果沒(méi)有命中,執(zhí)行查詢(xún)
    Object result = invocation.proceed();
    // 存入緩存
    return result;
}

7. 動(dòng)態(tài)數(shù)據(jù)源切換

場(chǎng)景:根據(jù)不同的業(yè)務(wù)需求動(dòng)態(tài)選擇數(shù)據(jù)源。

用途:實(shí)現(xiàn)讀寫(xiě)分離或多數(shù)據(jù)庫(kù)支持。

示例

@Override
public Object intercept(Invocation invocation) throws Throwable {
    String dataSourceKey = DataSourceContextHolder.getDataSourceKey();
    DynamicDataSource.setDataSourceKey(dataSourceKey);
    return invocation.proceed();
}

總結(jié)

MyBatis 攔截器為開(kāi)發(fā)者提供了靈活的擴(kuò)展能力,可以在 SQL 執(zhí)行的多個(gè)階段中注入自定義邏輯,從而實(shí)現(xiàn)多種高級(jí)功能。合理使用攔截器不僅能增強(qiáng)系統(tǒng)功能,還能提升性能和安全性。

到此這篇關(guān)于Spring Boot集成MyBatis-Plus 自定義攔截器實(shí)現(xiàn)動(dòng)態(tài)表名切換功能的文章就介紹到這了,更多相關(guān)Spring Boot MyBatis-Plus 動(dòng)態(tài)表名切換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot異步實(shí)現(xiàn)的8種方式

    SpringBoot異步實(shí)現(xiàn)的8種方式

    異步執(zhí)行對(duì)于開(kāi)發(fā)者來(lái)說(shuō)并不陌生,在實(shí)際的開(kāi)發(fā)過(guò)程中,很多場(chǎng)景多會(huì)使用到異步,本文主要介紹了SpringBoot異步實(shí)現(xiàn)的8種方式,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • Java實(shí)現(xiàn)List去重的方法詳解

    Java實(shí)現(xiàn)List去重的方法詳解

    本文用示例介紹Java的List(ArrayList、LinkedList等)的去重的方法。List去重的常用方法一般是:JDK8的stream的distinct、轉(zhuǎn)為HashSet、轉(zhuǎn)為T(mén)reeSet等,感興趣的可以了解一下
    2022-05-05
  • Java實(shí)現(xiàn)對(duì)華北、華南、華東和華中四個(gè)區(qū)域的劃分

    Java實(shí)現(xiàn)對(duì)華北、華南、華東和華中四個(gè)區(qū)域的劃分

    在Java中,通過(guò)定義枚舉類(lèi)、編寫(xiě)主程序和進(jìn)行測(cè)試,本文詳細(xì)介紹了如何劃分華北、華南、華東和華中四個(gè)區(qū)域,首先定義枚舉類(lèi)標(biāo)識(shí)區(qū)域,然后通過(guò)主程序接收用戶(hù)輸入并返回相應(yīng)區(qū)域,最后通過(guò)測(cè)試用例確保正確性,文章還介紹了甘特圖和餅狀圖的使用
    2024-09-09
  • SpringBoot @PostMapping接收HTTP請(qǐng)求的流數(shù)據(jù)問(wèn)題

    SpringBoot @PostMapping接收HTTP請(qǐng)求的流數(shù)據(jù)問(wèn)題

    這篇文章主要介紹了SpringBoot @PostMapping接收HTTP請(qǐng)求的流數(shù)據(jù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • Java實(shí)現(xiàn)冒泡排序簡(jiǎn)單示例

    Java實(shí)現(xiàn)冒泡排序簡(jiǎn)單示例

    冒泡排序(Bubble Sort)是一種簡(jiǎn)單的排序算法,它重復(fù)地走訪過(guò)要排序的數(shù)列,一次比較兩個(gè)元素,如果他們的順序錯(cuò)誤就把他們交換過(guò)來(lái),下面這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)冒泡排序的相關(guān)資料,需要的朋友可以參考下
    2023-06-06
  • Spring源碼解析之循環(huán)依賴(lài)的實(shí)現(xiàn)流程

    Spring源碼解析之循環(huán)依賴(lài)的實(shí)現(xiàn)流程

    這篇文章主要介紹了Spring源碼解析之循環(huán)依賴(lài)的實(shí)現(xiàn)流程,文章基于Java的相關(guān)內(nèi)容展開(kāi)循環(huán)依賴(lài)的實(shí)現(xiàn)流程,需要的小伙伴可以參考一下
    2022-07-07
  • Spring整合多數(shù)據(jù)源實(shí)現(xiàn)動(dòng)態(tài)切換的實(shí)例講解

    Spring整合多數(shù)據(jù)源實(shí)現(xiàn)動(dòng)態(tài)切換的實(shí)例講解

    下面小編就為大家?guī)?lái)一篇Spring整合多數(shù)據(jù)源實(shí)現(xiàn)動(dòng)態(tài)切換的實(shí)例講解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-07-07
  • 詳解Mybatis 傳遞參數(shù)類(lèi)型為L(zhǎng)ist的取值問(wèn)題

    詳解Mybatis 傳遞參數(shù)類(lèi)型為L(zhǎng)ist的取值問(wèn)題

    這篇文章主要介紹了詳解Mybatis 傳遞參數(shù)類(lèi)型為L(zhǎng)ist的取值問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • mybatis-plus使用generator實(shí)現(xiàn)逆向工程

    mybatis-plus使用generator實(shí)現(xiàn)逆向工程

    mybatis-plus-generator在3.5.0以及以后的版本使用新的方式逆向生成代碼,本文主要介紹了mybatis-plus使用generator實(shí)現(xiàn)逆向工程,具有一定的參考價(jià)值,感興趣的可以了解一下
    2022-05-05
  • jstl EL表達(dá)式遍歷Map的方法

    jstl EL表達(dá)式遍歷Map的方法

    這篇文章主要介紹了jstl EL表達(dá)式遍歷Map的方法的相關(guān)資料,需要的朋友可以參考下
    2016-12-12

最新評(píng)論

沂水县| 金昌市| 三台县| 灵璧县| 开封市| 胶州市| 三江| 朝阳市| 吉林市| 壤塘县| 韶关市| 旅游| 朝阳区| 金平| 甘德县| 万年县| 墨竹工卡县| 广饶县| 铜陵市| 赣州市| 新绛县| 法库县| 宁津县| 苏尼特左旗| 鄂伦春自治旗| 庆云县| 黄陵县| 定南县| 定兴县| 九龙城区| 新田县| 南平市| 鞍山市| 邢台市| 民丰县| 福泉市| 武汉市| 邢台县| 兖州市| 昂仁县| 石棉县|