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

MyBatis Plus中InnerInterceptor的實現(xiàn)

 更新時間:2025年03月17日 09:22:52   作者:十二同學啊  
本文主要介紹了MyBatis Plus中InnerInterceptor的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

在 Spring Boot 項目中使用 MyBatis Plus 時,你可能會遇到 InnerInterceptor 這個概念。 InnerInterceptor 是 MyBatis Plus 提供的一種輕量級 SQL 攔截器,它與傳統(tǒng)的 MyBatis 攔截器(Interceptor)有所不同,具有更簡單、更高效的特點,并且更專注于 SQL 執(zhí)行層面的攔截。本文將詳細介紹 InnerInterceptor 的原理、用法和最佳實踐,并提供代碼示例。

一、為什么需要 InnerInterceptor?

  • 更輕量級: 相比于傳統(tǒng)的 Interceptor,InnerInterceptor 更加輕量級,減少了不必要的攔截開銷,提高了性能。
  • 更專注于 SQL 執(zhí)行: InnerInterceptor 專注于 SQL 執(zhí)行層面,可以讓你更方便地修改 SQL 語句、參數(shù)或結果。
  • 簡化配置: InnerInterceptor 的配置更加簡單,無需手動注冊,MyBatis Plus 會自動識別并注冊。
  • 易于擴展:你可以通過實現(xiàn) InnerInterceptor 接口,自定義 SQL 攔截邏輯。
  • 與 MyBatis Plus 無縫集成:InnerInterceptor 與 MyBatis Plus 的其他功能無縫集成,可以更好地發(fā)揮 MyBatis Plus 的優(yōu)勢。
  • 內置豐富功能: MyBatis Plus 提供了許多內置的 InnerInterceptor 實現(xiàn),如分頁插件、樂觀鎖插件、SQL性能分析插件等,可以直接使用。

二、InnerInterceptor 與 Interceptor 的區(qū)別

  • 攔截范圍
    Interceptor 可以攔截 MyBatis 的 Executor、ParameterHandler、ResultSetHandler 和 StatementHandler 等組件,攔截范圍更廣。
    InnerInterceptor 主要攔截 SQL 執(zhí)行過程中的 StatementHandler,攔截范圍更窄,但更專注于 SQL 執(zhí)行。
  • 執(zhí)行時機
    Interceptor 可以攔截 SQL 執(zhí)行過程中的多個階段,例如參數(shù)處理、SQL 預編譯、結果處理等。
    InnerInterceptor 主要攔截 StatementHandler 的 prepare 和 query 方法,更專注于 SQL 語句的準備和執(zhí)行階段。
  • 配置方式
    Interceptor 需要在 MyBatis 配置文件或 Spring Bean 中手動注冊。
    InnerInterceptor 通過 MyBatis Plus 提供的 MybatisPlusInterceptor 統(tǒng)一注冊管理,無需手動注冊。
  • 代碼復雜度
    Interceptor 的代碼相對復雜,需要處理 Invocation 對象,并手動調用 proceed 方法。
    InnerInterceptor 的代碼更加簡潔,只需要重寫對應的方法。
  • 性能
    Interceptor 由于攔截范圍更廣,可能會帶來一定的性能開銷。
    InnerInterceptor 由于攔截范圍更窄,性能更高。

三、InnerInterceptor 的核心方法

  • void beforePrepare(StatementHandler sh, Connection connection,Integer transactionTimeout): 在 SQL 語句預編譯之前調用。
  • void beforeQuery(StatementHandler sh, Connection connection, Integer transactionTimeout): 在 SQL 語句執(zhí)行之前調用。
  • void afterQuery(StatementHandler sh, Connection connection, Integer transactionTimeout, Object result): 在 SQL 查詢執(zhí)行后調用。
  • void beforeUpdate(StatementHandler sh, Connection connection, Integer transactionTimeout): 在執(zhí)行 INSERT 或 UPDATE 語句之前調用。
  • void afterUpdate(StatementHandler sh, Connection connection, Integer transactionTimeout,Object result): 在執(zhí)行 INSERT 或 UPDATE 語句之后調用。

四、實踐:使用 InnerInterceptor 修改 SQL 語句

4.1 創(chuàng)建 InnerInterceptor 實現(xiàn)類:

import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.stereotype.Component;

import java.io.StringReader;
import java.sql.SQLException;

@Component
@Slf4j
public class MyInnerInterceptor implements InnerInterceptor {

    @Override
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
        String sql = boundSql.getSql();
        try {
            PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
            //sql處理
            String filterSql = addFilterCondition(sql);
            log.info("修改過后的sql:{}", filterSql);
            //修改sql
            mpBs.sql(filterSql);
        } catch (Exception e) {
            log.warn("動態(tài)修改sql:{}異常", sql, e);
            throw new SQLException("添加數(shù)據(jù)權限異常");
        }
    }

    public String addFilterCondition(String originalSql) throws JSQLParserException {
        CCJSqlParserManager parserManager = new CCJSqlParserManager();
        Select select = (Select) parserManager.parse(new StringReader(originalSql));
        PlainSelect plain = (PlainSelect) select.getSelectBody();
        Expression where_expression = plain.getWhere();
        // 這里可以根據(jù)需要增加過濾條件
        if (where_expression == null) {
            plain.setWhere(CCJSqlParserUtil.parseCondExpression("age = 35"));
        }
        return plain.toString();
    }
}

4.2 配置 MybatisPlusInterceptor

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.extend.chk.interceptor.MyInnerInterceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.List;

@Configuration
public class MyBatisPlusConfig {

    @Autowired
    private List<SqlSessionFactory> sqlSessionFactoryList;

    @Autowired
    private MyInnerInterceptor myInnerInterceptor;

    /**
     * 添加Mybatis攔截器
     * 主要是為了保證數(shù)據(jù)權限攔截器在分頁插件攔截器之前執(zhí)行sql的修改,如果不在這里手動添加的話,PageInterceptor會先執(zhí)行
     * 先添加的攔截器后執(zhí)行
     */
    @PostConstruct
    public void addMybatisInterceptor() {
        for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
            org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
            //將數(shù)據(jù)權限攔截器添加到MybatisPlusInterceptor攔截器鏈
            MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
            mybatisPlusInterceptor.addInnerInterceptor(myInnerInterceptor);
            //先添加PageHelper分頁插件攔截器,再添加MybatisPlusInterceptor攔截器
            //configuration.addInterceptor(new PageInterceptor());
            configuration.addInterceptor(mybatisPlusInterceptor);
        }
    }
}

4.3 使用 InnerInterceptor

現(xiàn)在,你執(zhí)行任何 SQL 語句,都會被 InnerInterceptor 攔截,你可以看到 SQL 語句已經(jīng)被修改。

修改過后的sql:SELECT count(0) FROM t_user_info WHERE age = 35
修改過后的sql:SELECT id, name, password, age, status, last_login_time, token, create_by, create_time, update_by, update_time, remark FROM t_user_info WHERE age = 35 LIMIT ?

五、內置攔截器

除了自定義攔截器外,MyBatis-Plus 還提供了多個內置攔截器,可以直接使用或作為參考來創(chuàng)建自己的攔截器。以下是幾個常用的內置攔截器:

  • PaginationInterceptor:分頁插件,支持多種數(shù)據(jù)庫的分頁查詢。
  • PerformanceAnalyzerInterceptor:性能分析插件,記錄每條 SQL 的執(zhí)行時間和影響行數(shù)。
  • OptimisticLockerInterceptor:樂觀鎖插件,用于防止并發(fā)更新時的數(shù)據(jù)覆蓋問題。
  • BlockAttackInterceptor:阻止惡意攻擊插件,防止批量刪除或更新操作導致數(shù)據(jù)丟失。

六、常見應用場景

  • SQL 日志記錄:如上文所示,記錄每次 SQL 執(zhí)行的時間、參數(shù)及結果,便于調試和性能分析。
  • 分頁插件:動態(tài)地為查詢語句添加分頁條件,而無需修改原有的 Mapper 文件。
  • SQL 性能監(jiān)控:統(tǒng)計每條 SQL 的執(zhí)行次數(shù)、平均耗時等指標,幫助識別潛在的性能瓶頸。
  • 緩存實現(xiàn):基于攔截器實現(xiàn)簡單的查詢結果緩存,減少不必要的數(shù)據(jù)庫訪問。
  • 數(shù)據(jù)脫敏:在查詢結果返回之前,對敏感字段進行加密或替換,確保數(shù)據(jù)安全。
  • 權限控制:在 SQL 執(zhí)行前檢查用戶權限,防止未經(jīng)授權的操作。

七、最佳實踐

  • 按需選擇攔截器: 根據(jù)實際需求選擇合適的攔截器,如果需要修改 SQL 語句、參數(shù)或結果,可以使用 InnerInterceptor,如果需要攔截 MyBatis 的其他組件,可以使用 Interceptor。
  • 細粒度控制: 可以根據(jù) MappedStatement 的 ID 或 SQL 語句內容,細粒度控制 InnerInterceptor 的執(zhí)行范圍。
  • 使用內置的 InnerInterceptor: MyBatis Plus 提供了許多內置的 InnerInterceptor 實現(xiàn),如分頁插件、樂觀鎖插件、SQL 性能分析插件等,可以直接使用,無需重復開發(fā)。
  • 避免耗時操作: InnerInterceptor 會在 SQL 執(zhí)行的關鍵節(jié)點執(zhí)行,避免在其中執(zhí)行耗時的操作,以免影響性能。
  • 異常處理: 在 InnerInterceptor 方法中使用 try-catch 代碼塊處理可能拋出的異常,避免影響正常業(yè)務邏輯。
  • 配置順序: 如果存在多個 InnerInterceptor,Mybatis Plus 會根據(jù) addInnerInterceptor 方法的調用順序進行執(zhí)行。
  • 使用 MyBatis Plus 工具類: MyBatis Plus 提供了一些工具類,例如 PluginUtils,可以方便地訪問和修改 SQL 語句、參數(shù)等信息。

到此這篇關于MyBatis Plus中InnerInterceptor的實現(xiàn)的文章就介紹到這了,更多相關MyBatisPlus InnerInterceptor內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家! 

相關文章

最新評論