Mybatis攔截器介紹


一、Mybatis攔截器介紹

  Mybatis攔截器設計的思路是為了供用戶靈活的實現自己的邏輯,而不動mybatis固有的邏輯,簡而言之就是如果Mybatis是一只蝦,我們要做的是將蝦肉掏空,放入自己喜歡吃的東西進去,而依舊保持嚇得殼身。通過Mybatis攔截器我們能攔截某些方法的調用,我們可以選擇在這些被攔截方法執行前后加上我們自己的邏輯,達到豐富方法的效果;也可以在執行這些方法的時候攔截住,轉而實現自己設計的方法,而最后不執行被攔截的方法。Mybatis中有很多核心對象,大致如下:

SqlSession 負責和數據庫進行交互,實現完成常對數據操作的增刪改查功能
Executor Mybatis執行器,調度的核心,負責SQL語句的生成和維護
StatementHandler 封裝並操作Jdbc statement,例如設置參數,將statement結果集轉化為List集合
ParameterHandler 負責將用戶傳遞的參數轉換為Jdbc statement所需要的參數進行傳遞
ResultSetHandler 負責將Jdbc返回的ResultSet結果集對象轉換為List類型的集合
TypeHandler 負責將java數據類型和Jdbc數據類型之間的轉換和映射
MappedStatement MappedStatement維護了一條mapper.xml文件里面 select 、update、delete、insert節點的封裝
Configuration MyBatis所有的配置信息都維持在Configuration對象之中
BoundSql 表示動態生成的SQL語句以及相應的參數信息

 

 

 

 

 

 

 

 

 

 

 

Mybatis攔截器並不能攔截mybatis核心對象中所有方法,相反的,MyBatis攔截器可以攔截四個對象中方法,分別是:Executor、StatementHandler、ParameterHandler 和ResultSetHandler。

 1. Executor

Executor是mybatis核心接口,數據庫增刪改語句是通過Executor接口的update方法進行的,查詢是通過query方法進行,代碼如下:

public interface Executor {
    /*
    * 執行update/insert/delete
    * */
    int update(MappedStatement ms , Object paramter)throws SQLException;

    /*
    * 執行查詢,先在緩存中查找
    * Mybatis提供了一個簡單的邏輯分頁使用類RowBounds(物理分頁當然就是我們在sql語句中指定limit和offset值),在DefaultSqlSession提供的某些查詢接口中我們可以看到RowBounds是作為參數用來進行分頁的
    * */
    <E> List<E> query(MappedStatement ms , Object paramter , RowBounds rowBounds , ResultSetHandler resultSetHandler , CacheKey cacheKey , BoundSql boundSql)throws SQLException;

    /*
    * 執行查詢
    * */
     <E> List<E> query(MappedStatement ms , Object paramter , ResultSetHandler resultSetHandler)throws SQLException;

     /*
     * 執行查詢,結果放在Cursor里面
     * */
     <E> Cursor<E> queryCursor(MappedStatement ms , Object paramter)throws SQLException;
     
}

2. ParameterHandler

ParameterHandler用來設置參數規則,當StatementHandler使用prepare()方法后,接下來就是使用它來設置參數。所以如果有對參數做自定義邏輯處理的時候,可以通過攔截ParameterHandler來實現。ParameterHandler里面可以攔截的方法解釋如下:

public interface ParameterHandler {
    /*
    * 設置參數規則的時候使用——PreparedStatement
    * */
    void setParamters(PreparedStatement ps) throws SQLException;
}

3. StatementHandler

StatementHandler負責處理Mybatis與JDBC之間Statement的交互。

 

public interface StatementHandler {
    /*
    * 從連接中獲取一個Statement
    * */
    Statement prepare(Connection conn , Integer transactionTimeout)throws SQLException;

    /*
    * 設置statement執行里需要的參數
    * */
    void paramterize(Statement statement)throws SQLException;

    /**
     * 批量
     */
    void batch(Statement statement)
            throws SQLException;

    /**
     * 更新:update/insert/delete語句
     */
    int update(Statement statement)
            throws SQLException;

    /**
     * 執行查詢
     */
    <E> List<E> query(Statement statement, ResultHandler resultHandler)
            throws SQLException;

    <E> Cursor<E> queryCursor(Statement statement)
            throws SQLException;
}

一般只攔截prepare方法。

在Mybatis里面RoutingStatementHandler是SimpleStatementHandler(對應Statement)、PreparedStatementHandler(對應PreparedStatement)、CallableStatementHandler(對應CallableStatement)的路由類,所有需要攔截StatementHandler里面的方法的時候,對RoutingStatementHandler做攔截處理就可以了,如下的寫法可以過濾掉一些不必要的攔截類。

@Intercepts({
        @Signature(
                type = Statement.class ,
                method =  "prepare",
                args = {Connection.class , Integer.class}
        )
})
public class TableShardInterceptor implements Interceptor {
    /*
    * mybatis運行時要執行的攔截方法
    * */
    @Override
    public Object intercept(Invocation invocation ) throws Throwable{
        if(invocation.getTarget()instanceof RoutingStatementHandler){
            //to do 自己的邏輯
        }
        return invocation.proceed();
    }
    /*
    * target:攔截對象
    *
    * */
    @Override
    public Object plugin(Object target){
        // 當目標類是StatementHandler類型時,才包裝目標類,否者直接返回目標本身,減少目標被代理的次數
        return (target instanceof RoutingStatementHandler)? Plugin.wrap(target,this):target;
    }
    //實現插件參數傳遞
    @Override
    public void setProperties(Properties properties){

    }


}

 4. ResultSetHandler

  ResultSetHandler用於對查詢到的結果做處理。所以如果你有需求需要對返回結果做特殊處理的情況下可以去攔截ResultSetHandler的處理。ResultSetHandler里面常用攔截方法如下:

public interface ResultSetHandler {
    /*
    * 將statement執行后產生的結果集(可能有多個結果集)映射為結果表
    * */
    <E> List<E> handResultSets(Statement stmt)throws SQLException;
    <E> List<E> handleCursorResultSet(Statement stmt)throws SQLException;

    /*
    * 處理存儲過程執行后的輸出參數
    * */
    void handleOutputParameters(CallableStatement cs) throws SQLException;
}

至此,攔截器介紹由此結束。

部分內容參考自:https://blog.csdn.net/wuyuxing24/article/details/89343951


免責聲明!

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



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