Mybatis攔截器介紹及其應用

Mybatis攔截器介紹及其應用

1、介紹

Mybatis攔截器設計的初衷就是為了供用戶在某些時候可以實現自己的邏輯而不必去動Mybatis固有的邏輯。通過Mybatis攔截器我們可以攔截某些方法的調用,我們可以選擇在這些被攔截的方法執行前后加上某些邏輯,也可以在執行這些被攔截的方法時執行自己的邏輯而不再執行被攔截的方法。所以Mybatis攔截器的使用范圍是非常廣泛的。

2、Mybatis部分核心對象

Mybatis核心對象解釋
SqlSession作為MyBatis工作的主要頂層API,表示和數據庫交互的會話,完成必要數據庫增刪改查功能
ExecutorMyBatis執行器,是MyBatis 調度的核心,負責SQL語句的生成和查詢緩存的維護
StatementHandler封裝了JDBC Statement操作,負責對JDBC statement 的操作,如設置參數、將Statement結果集轉換成List集合
ParameterHandler負責對用戶傳遞的參數轉換成JDBC Statement 所需要的參數
ResultSetHandler負責將JDBC返回的ResultSet結果集對象轉換成List類型的集合
TypeHandler負責java數據類型和jdbc數據類型之間的映射和轉換
MappedStatementMappedStatement維護了一條mapper.xml文件里面 select 、update、delete、insert節點的封裝
SqlSource負責根據用戶傳遞的parameterObject,動態地生成SQL語句,將信息封裝到BoundSql對象中,并返回
BoundSql表示動態生成的SQL語句以及相應的參數信息
ConfigurationMyBatis所有的配置信息都維持在Configuration對象之中

3、攔截器種類

3.1、ParameterHandler 參數攔截器:

ParameterHandler攔截器類型用于攔截MyBatis的參數處理過程。它在參數設置到PreparedStatement對象之前攔截并修改參數。你可以通過實現ParameterHandler接口來自定義參數處理邏輯,例如對參數進行加密、解密、校驗或轉換等操作。

3.2、ResultSetHandler 結果集攔截器:

ResultSetHandler攔截器類型用于攔截MyBatis的結果集處理過程。它在從JDBC結果集中獲取數據并映射到Java對象或集合之前攔截并修改結果。你可以通過實現ResultSetHandler接口來自定義結果集處理邏輯,例如對結果進行加工、過濾、緩存或轉換等操作。

3.3、StatementHandler 語句攔截器:

StatementHandler攔截器類型用于攔截MyBatis的SQL語句處理過程。它在SQL語句執行之前攔截并修改SQL語句、設置參數或進行其他操作。你可以通過實現StatementHandler接口來自定義SQL語句處理邏輯,例如動態修改SQL語句、添加分頁邏輯、實現緩存等。

3.4、Executor執行攔截器:

攔截執行器的方法,主要負責SQL的執行,包括INSERT、UPDATE、DELETE等操作以及SELECT查詢操作。通過攔截Executor接口的方法,可以實現對數據庫操作前后的統一處理,比如開啟事務、記錄日志、分頁處理、二級緩存控制等。

4、實際應用

4.1、自定義攔截器
package com.springboot.cli;import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import java.lang.reflect.Method;
import java.util.Properties;/*** 類說明:@Intercepts注解用于標注一個類是一個MyBatis攔截器;@Signature注解用于指定一個方法的簽名,其中包括方法所在的接口、方法名以及方法的參數列表* type參數指定了被攔截的接口類型,比如Executor.class表示要攔截Executor接口的方法。* method參數指定了要攔截的方法名。* args參數是一個Class數組,用來指定方法的參數類型列表,通過這些參數類型可以唯一確定要攔截的方法。* 如果需要攔截多個不同類型的方法,可以在@Intercepts注解中指定多個@Signature注解。** @author liangtl* @Date 2024/7/14*/
@Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class MybatisInterceptor implements Interceptor {private Properties properties;@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 代理對象Object target = invocation.getTarget();// 代理方法Method method = invocation.getMethod();// 方法參數Object[] args = invocation.getArgs();// 如果args長度大于1,說明有附帶的其他參數Object parameter = null;if (args.length > 1) {// 查詢參數parameter = args[1];}MappedStatement mappedStatement = (MappedStatement) args[0];// sqlIdString sqlId = mappedStatement.getId();// 拼接完成的sqlString sql = mappedStatement.getBoundSql(parameter).getSql();// 這里一定需要使用invocation.proceed()返回,以保證sql繼續執行。// 如果想進行判斷然后中斷sql執行,可以返回emptyList。return invocation.proceed();}/*** 生成MyBatis攔截器代理對象(非必須)*/@Overridepublic Object plugin(Object target) {if(target instanceof StatementHandler){//調用插件return Plugin.wrap(target, this);}return target;}/*** 設置插件屬性(直接通過Spring的方式獲取屬性,所以這個方法一般也用不到)* 項目啟動的時候數據就會被加載*/@Overridepublic void setProperties(Properties properties) {//賦值成員變量,在其他方法使用。this.properties = properties;}
}
4.2、注冊攔截器

攔截器注冊有兩種方式,一種是在配置文件中配置,第二種是通過代碼的形式。

這里演示使用代碼進行攔截器注冊。

package com.springboot.cli;import org.apache.ibatis.datasource.pooled.PooledDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;import javax.sql.DataSource;/*** 數據源配置Demo** @author liangtl* @Date 2024/7/14*/@Configuration
public class DataSourceConfig {@Value("${test.datasource.url}")private String url;@Value("${test.datasource.username}")private String user;@Value("${test.datasource.password}")private String password;@Value("${test.datasource.driverClassName}")private String driverClass;@Bean(name = "dataSource")public DataSource dataSource() {PooledDataSource dataSource = new PooledDataSource();dataSource.setDriver(driverClass);dataSource.setUrl(url);dataSource.setUsername(user);dataSource.setPassword(password);return dataSource;}@Bean(name = "transactionManager")public DataSourceTransactionManager dataSourceTransactionManager() {return new DataSourceTransactionManager(dataSource());}@Bean(name = "sqlSessionFactory")public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(dataSource);sessionFactory.setPlugins(new MybatisInterceptor());// 設置mapper文件位置sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:**/**/mapper/*.xml"));// 設置實體類映射規則: 下劃線 -> 駝峰org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();configuration.setMapUnderscoreToCamelCase(true);sessionFactory.setConfiguration(configuration);return sessionFactory.getObject();}
}

在我們定義的sqlSessionFactory這個bean中,sessionFactory.setPlugins(new MybatisInterceptor());這一行代碼就是我們注冊自定義攔截器的地方。

至此,Mybatis攔截器就已經從自定義到注冊完成,當我們注入的是sqlSessionFactory這個Factory時,攔截器就會生效。

5、擴展

有些時候我們可能需要在攔截器中注入一些我們需要的類來完成一些特定的邏輯,于是我們默認使用@Autowired去將其注入,結果發生代碼執行時報了NPE,因為注入的屬性為null。

原因如下:

因為攔截器對象是由Servlet容器負責創建和管理的,而不是由Spring容器管理的。因此,Spring容器無法感知并注入攔截器中的屬性。

現在已經知道原因了,那么就可以解決這個問題。

方法一:將攔截器作為一個Spring Bean進行配置,交由Spring容器進行管理

方法二:既然攔截器中無法注入,那就不注入了。新增一個有參構造使用構造器的方式注入屬性

方法三:可以通過實現ApplicationContextAware接口或者直接在攔截器中獲取ApplicationContext對象,然后從ApplicationContext中獲取需要的Bean

參考博客:

Mybatis攔截器_@intercepts-CSDN博客

MyBatis攔截器四種類型和自定義攔截器的使用流程_mybatis 攔截器-CSDN博客

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/45407.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/45407.shtml
英文地址,請注明出處:http://en.pswp.cn/web/45407.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Pycharm與Gitlab交互

環境準備 1、下載配置好本地Git 2、配置Pycharm上的Git 3、gitlab賬號 Gitlab配置 Gitlab配置中文 賬號》設置》偏好設置》簡體中文 創建項目 命令行操作 打開項目會展示以下步驟 在pycharm克隆gitlab的項目 通過菜單欄 1、在PyCharm的頂部菜單欄中,選擇“V…

本地部署,Flash Diffusion: 加速條件擴散模型實現快速圖像生成

目錄 引言 技術背景 Flash Diffusion 的架構與原理 Flash Diffusion 的主要特點 本地部署 運行結果 實驗結果與分析 應用實例 結論 GitHub - gojasper/flash-diffusion: Official implementation of ? Flash Diffusion ?: Accelerating Any Conditional Diffusion M…

Linux系統搭建輕量級個人博客VanBlog并一鍵發布公網遠程訪問

文章目錄 前言1. Linux本地部署2. VanBlog簡單使用3. 安裝內網穿透4. 創建公網地址5. 創建固定公網地址 前言 今天和大家分享如何在Linux Ubuntu系統搭建一款輕量級個人博客VanBlog,并結合cpolar內網穿透軟件生成公網地址,輕松實現隨時隨地遠程訪問本地…

相交鏈表+判斷環型鏈表+求環型鏈表的入口節點

鏈表OJ題 一.相交鏈表二.判斷環型鏈表三.求環型鏈表的入口節點 一.相交鏈表 相交鏈表 相交:兩個鏈表從頭開始遍歷,尾節點一定是同一個節點。 情況一:當兩個鏈表長度相同時: 情況二:當兩個鏈表長度不同時&#xff1…

考研黨暑假回家還是留校,暑假回家就一定完蛋嗎?

考研我建議最好還是留校,因為環境比較好! 并不是說回家復習就一定不好,回家要面臨三大“敵人”: 1、我們本身的惰性,這個無需多言,在自己熟悉的環境,自己一個人,手機電腦網絡零食俱…

python條件

條件語句 if語句 if...else語句 if...elif...else語句 嵌套 is is 是一個身份運算符,用于比較兩個對象的身份,即它們在內存中的地址是否相同。這與比較兩個對象是否相等的 運算符不同。 運算符比較的是兩個對象的值是否相等。 比較對象 比較基本數據…

【Unity】RPG2D龍城紛爭(十一)戰斗系統之回合制驅動

更新日期:2024年7月11日。 項目源碼:第五章發布(正式開始游戲邏輯的章節) 索引 簡介一、開始關卡二、進入指定回合三、玩家結束當前回合四、進入下一回合五、通關條件六、檢測關卡狀態簡介 通過前兩篇的工作,我們的角色已經能夠進行移動、戰斗了,此刻,便進入第三個板塊…

React基礎學習-Day04

React基礎學習-Day04 常見的鉤子函數及基礎使用方式 1.useState useState 是 React 的一個 Hook,用于在函數組件中添加狀態。它返回一個狀態變量和一個更新該狀態的函數。與類組件的 this.state 和 this.setState 相對應,useState 讓函數組件也能擁有…

存儲實驗:Linux掛載iscsi硬盤與華為OceanStor創建LUN全流程

目錄 目的環境規劃實驗實驗流程Centos配置0. 關閉防火墻1. 設置網卡信息2. 配置路由3. iscsiadm連接存儲 iSCSI LUN創建(以華為OceanStor為例)驗證1. 驗證是否成功2. 開啟自動掛載 目的 實現Linux連接iscsi硬盤,同時實現開機自啟掛載 環境規…

掌握本地倉儲:Gradle本地倉庫配置全指南

掌握本地倉儲:Gradle本地倉庫配置全指南 在構建自動化的領域中,Gradle以其靈活性和強大的依賴管理功能脫穎而出。管理項目依賴時,經常需要配置本地倉庫以優化構建速度、控制依賴版本或支持離線構建。本文將深入探討如何在Gradle中配置本地倉…

JAVA----泛型

泛型 認識泛型 定義類、接口、方法時,同時聲明了一個或者多個類型變量(如:) ,稱為泛型類、泛型接口,泛型方法、它們統稱為泛型。 作用:利用泛型,可以限制集合存儲數據的類型. 泛型…

Gitee簡易使用流程(后期優化)

目錄 1.修改用戶名 2.文件管理 新建文件/文件夾流程如下: 上傳文件流程如下: 以主頁界面為起點 1.修改用戶名 點解右上角的頭像--> 點擊“賬號設置” 點擊左邊欄里的“個人資料“ 直接修改用戶名即可 2.文件管理 選擇一個有修改權限倉庫&#…

【從0到1進階Redis】主從復制

筆記內容來自B站博主《遇見狂神說》:Redis視頻鏈接 1、概念 主從復制,是指將一個臺 Redis 服務器的數據,復制到其他的 Redis 服務器。前者稱為主節點(master/leader),后者稱為從節點(slave/foll…

this指向解析

先看題目: 第一題: var name window var person1 { name: person1, show1: function () { console.log(this.name) }, show2: () > console.log(th show3: function () { return function () { …

MFC之對話框--重繪元文件

文章目錄 實現示例展示需要繪制的窗口/位置控件位置更新下一次示例粗細滑動部分更新 重繪元文件(窗口變化內容消失)方法一:使用元文件方法二:兼容設備方法三:使用自定義類存儲繪圖數據除畫筆外功能處理畫筆功能處理 保…

springmvc1

以前的servlet程序: springmvc 不同的處理器:不同的方法或者處理類 所有的請求都會經過dispathcherservlet的doservice方法: mvc原理: 前端控制器:jsp或者什么東西

Python字符串基礎與高級操作

在Python中,字符串是不可變的數據類型,用于存儲一系列的字符。它們可以被創建、訪問、操作和格式化,但一旦創建,其內容就不能改變。下面是一篇關于Python字符串技術的詳細講解,包括創建、訪問、更新、轉義、運算符、格…

Phpstudy 2018 之xhcms搭建

1、由于直接訪問根目錄無法進入網站 2、所以采用搭建網站,第一使用系統服務模式、選擇php-5.4.45Apache模式 3、網站域名為本地ip地址或者127.0.0.1、端口8085 4、在navicat創建名字為xjcms的數據庫,并導入sql數據庫文件 5、瀏覽器輸入127.0.0.1:8085直接…

中風傷寒、感冒、六經辨證筆記

目錄 基礎傳經的原因傳經的過程及速度傳經的危害感冒時體痛頭痛的原因根據頭痛的位置辨經 太陽病太陽中風外風內熱 表虛感冒顆粒(桂枝葛根湯) 少陽病辨病總結傷寒論原文半表半里太陽為開,陽明為闔,少陽為樞膽的作用幫助腸胃消化、…

deepstream讀取mp4文件及不同類型視頻輸入bug解決

在deepstream中使用mp4文件,與rtsp類似,使用uridecodebin即可,(可見官方test.py文件) def create_source_bin(index, uri):print("Creating source bin")# Create a source GstBin to abstract this bins c…