欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

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

一、引言

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

二、項目配置

1. 集成 MyBatis-Plus

簡單說明如何在 Spring Boot 中引入 MyBatis-Plus 并配置。

2. 依賴添加

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

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

1. 攔截器原理

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

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

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

@Component
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class DynamicTableInterceptor implements Interceptor {
  	/**
     * 使用ThreadLocal來存儲線程特有的數(shù)據(jù),這里用于存儲動態(tài)表名
     */
    private static final ThreadLocal<String> TABLE_NAME_HOLDER = new ThreadLocal<>();
    /**
     * 設(shè)置動態(tài)表名
     *
     * @param tableName 需要設(shè)置的表名,由調(diào)用者指定
     *                  此方法允許在運行時動態(tài)地設(shè)置數(shù)據(jù)庫表名,以便在多數(shù)據(jù)源或動態(tài)表名的場景下靈活地切換表
     */
    public static void setDynamicTableName(String tableName) {
        TABLE_NAME_HOLDER.set(tableName);
    }
    /**
     * 清除當(dāng)前線程中的動態(tài)表名
     * 此方法用于清除ThreadLocal中存儲的表名信息,以避免內(nèi)存泄漏
     * 它應(yīng)在每次使用動態(tài)表名后調(diào)用,確保不會對后續(xù)的請求產(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) {
            /**
             * 從實體類的@tableName中獲取表名,必須在實體類上面添加@tableName注解
             * 實體類中的@tableName注解中的值,必須是數(shù)據(jù)庫中的表名,否則會報錯
             * 例如 :@TableName("t_user_"),數(shù)據(jù)庫是根據(jù)月份來的,在這里替換則需要根據(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. 使用攔截器動態(tài)設(shè)置表名

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

四、其他場景

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

1. SQL 日志記錄與審計

  • 場景:記錄每次執(zhí)行的 SQL 語句、參數(shù)、執(zhí)行時間等信息。
  • 用途:用于 SQL 審計、性能監(jiā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. 多租戶數(shù)據(jù)隔離

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

示例

@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ù)加密與解密

  • 場景:對敏感數(shù)據(jù)(如身份證號、電話等)在 SQL 操作時進(jìn)行自動加密或解密。
  • 用途:提高數(shù)據(jù)安全性,確保數(shù)據(jù)存儲符合安全規(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. 自動分頁處理

  • 場景:在執(zhí)行查詢時自動添加分頁邏輯,避免手動分頁處理。
  • 用途:簡化分頁查詢的代碼。

示例

@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)限控制

  • 場景:根據(jù)用戶角色或權(quán)限,自動添加數(shù)據(jù)過濾條件。
  • 用途:確保用戶只能訪問被授權(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 + "'";
    // 動態(tài)修改 SQL
    return invocation.proceed();
}

6. 緩存增強(qiáng)

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

示例

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

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

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

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

示例

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

總結(jié)

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

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

相關(guān)文章

  • Spring Session的使用示例

    Spring Session的使用示例

    最近團(tuán)隊一個項目需要使用Session,之前沒有在實際項目中使用過Spring-Session,這里記錄一下使用的過程
    2021-06-06
  • 通過java字節(jié)碼分析學(xué)習(xí)對象初始化順序

    通過java字節(jié)碼分析學(xué)習(xí)對象初始化順序

    今天用了jmock對進(jìn)行單元測試編碼,發(fā)現(xiàn)一個比較奇怪的語法,static使用方法,見下面例子
    2013-11-11
  • Java join 線程控制用法

    Java join 線程控制用法

    Java join 線程控制用法,需要的朋友可以參考一下
    2013-03-03
  • 使用Runnable實現(xiàn)數(shù)據(jù)共享

    使用Runnable實現(xiàn)數(shù)據(jù)共享

    這篇文章主要為大家詳細(xì)介紹了如何使用Runnable實現(xiàn)數(shù)據(jù)共享,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • IntelliJ?IDEA?2022.2.1最新永久激活破解教程(持續(xù)更新)

    IntelliJ?IDEA?2022.2.1最新永久激活破解教程(持續(xù)更新)

    這篇文章主要介紹了IntelliJ?IDEA?2022.2.1最新永久激活破解教程(持續(xù)更新),小編測試這種激活工具也適用idea2022以下所有版本,本篇教程整理的比較詳細(xì),匯總了idea各個版本的激活工具,激活方法多種多樣,大家選擇一種即可,感興趣的朋友跟隨小編一起看看吧
    2022-09-09
  • idea將maven項目改成Spring boot項目的方法步驟

    idea將maven項目改成Spring boot項目的方法步驟

    這篇文章主要介紹了idea將maven項目改成Spring boot項目的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • java實現(xiàn)計算器功能

    java實現(xiàn)計算器功能

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)計算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-02-02
  • 代碼生成器MyBatisX:自動生成代碼方式

    代碼生成器MyBatisX:自動生成代碼方式

    MyBatisX是一款提高開發(fā)效率的插件,可以自動生成Mapper、XML和Java實體類代碼,并支持?jǐn)?shù)據(jù)庫表的重置和JAP提示,安裝步驟簡單,只需在IDEA的Plugin市場搜索并安裝MyBatisX,然后打開數(shù)據(jù)庫窗口選擇表進(jìn)行生成即可
    2024-11-11
  • java利用時間格式生成唯一文件名的方法

    java利用時間格式生成唯一文件名的方法

    這篇文章主要介紹了java利用時間格式生成唯一文件名的方法,需要的朋友可以參考下
    2017-01-01
  • Jdbc的步驟以及簡單實現(xiàn)代碼

    Jdbc的步驟以及簡單實現(xiàn)代碼

    下面小編就為大家?guī)硪黄狫dbc的步驟以及簡單實現(xiàn)代碼。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-07-07

最新評論