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

mybatis實(shí)戰(zhàn)之?dāng)r截器解讀

 更新時(shí)間:2023年03月20日 15:10:04   作者:FrankyD90  
這篇文章主要介紹了mybatis實(shí)戰(zhàn)之?dāng)r截器解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

mybatis實(shí)戰(zhàn)之?dāng)r截器

在服務(wù)的開發(fā)過程中,往往存在這樣的需求,針對(duì)業(yè)務(wù),實(shí)現(xiàn)對(duì)數(shù)據(jù)庫操作語句做統(tǒng)一的處理。

比如對(duì)某些敏感數(shù)據(jù)如用戶姓名、手機(jī)號(hào)等坐脫敏處理保存和查詢、對(duì)未實(shí)現(xiàn)權(quán)限的查詢通過添加關(guān)聯(lián)查詢實(shí)現(xiàn)權(quán)限控制查詢結(jié)果等等。

這時(shí),mybatis框架提供了攔截器的方式,允許在映射語句執(zhí)行過程中的某一點(diǎn)進(jìn)行攔截調(diào)用,進(jìn)行自己的業(yè)務(wù)處理。

1、使用方法

這里參考了官網(wǎng)的使用說明,只需實(shí)現(xiàn) Interceptor 接口,并在類中指定想要攔截的方法簽名即可。

比如:

@Intercepts({@Signature(
? type= Executor.class,
? method = "update",
? args = {MappedStatement.class,Object.class})})
public class ExamplePlugin implements Interceptor {
? private Properties properties = new Properties();
? public Object intercept(Invocation invocation) throws Throwable {
? ? // implement pre processing if need
? ? Object returnObject = invocation.proceed();
? ? // implement post processing if need
? ? return returnObject;
? }
? public void setProperties(Properties properties) {
? ? this.properties = properties;
? }
}

然后在mybatis的配置文件中,添加插件的對(duì)應(yīng)配置即可。

<!-- mybatis-config.xml -->
<plugins>
? <plugin interceptor="org.mybatis.example.ExamplePlugin">
? ? <property name="someProperty" value="100"/>
? </plugin>
</plugins>

我們也可以在代碼中添加,下面給出在spring中

//通過spring查找SqlSessionFactory對(duì)象的邏輯在此省略
SqlSessionFactory sqlSessionFactory = (SqlSessionFactory) var3;
org.apache.ibatis.session.Configuration c = sqlSessionFactory.getConfiguration();
c.addInterceptor(interceptor);

分別加上處理的業(yè)務(wù)邏輯,這個(gè)攔截器就可以使用了。

2、需要注意的地方

第一節(jié)簡(jiǎn)單介紹了,攔截器的使用方法,但在實(shí)際項(xiàng)目中這樣還遠(yuǎn)遠(yuǎn)不夠。

筆者在本節(jié)列舉了一些需要注意的地方,供大家思考討論。

攔截器的執(zhí)行順序

攔截器的調(diào)用順序分為兩大種,第一種是攔截的不同對(duì)象,第二種是指攔截同一種對(duì)象的同一個(gè)方法。

第一種情況,例如攔截 Executor 和 攔截 StatementHandler 就屬于不同的攔截對(duì)象, 這兩類的攔截器在整體執(zhí)行的邏輯上是不同的。

StatementHandler 屬于 Executor 執(zhí)行過程中的一個(gè)子過程。

所以這兩種不同類別的插件在配置時(shí),一定是先執(zhí)行 Executor 的攔截器,然后才會(huì)輪到 StatementHandler。

所以這種情況下配置攔截器的順序就不重要了,在 MyBatis 邏輯上就已經(jīng)控制了先后順序。

第二種情況,例如都攔截 Executor 的 query 方法,這時(shí)你配置攔截器的順序就會(huì)對(duì)這里有影響了。比如配置如下。

<plugins>
? ? <plugin interceptor="com.github.pagehelper.ExecutorQueryInterceptor1"/>
? ? <plugin interceptor="com.github.pagehelper.ExecutorQueryInterceptor2"/>
? ? <plugin interceptor="com.github.pagehelper.ExecutorQueryInterceptor3"/>
</plugins>

前面我們配置攔截器的順序是1,2,3。在這里也會(huì)按照 1,2,3 的順序被層層代理,代理后的結(jié)構(gòu)如下:

Interceptor3:{
? ? Interceptor2: {
? ? ? ? Interceptor1: {
? ? ? ? ? ? target: Executor
? ? ? ? }
? ? }
}

然后到執(zhí)行的邏輯:

Interceptor3 前置處理
Interceptor2 前置處理
Interceptor1 前置處理  
Object result = executor.query(4個(gè)參數(shù)方法);     
Interceptor1 后續(xù)處理   
Interceptor2 后續(xù)處理  
Interceptor3 后續(xù)處理   
return result;

順序就是 3>2>1>Executor>1>2>3。MyBatis的攔截器采用責(zé)任鏈設(shè)計(jì)模式,多個(gè)攔截器之間的責(zé)任鏈?zhǔn)峭ㄟ^動(dòng)態(tài)代理組織的。

我們一般都會(huì)在攔截器中的intercept方法中往往會(huì)有invocation.proceed()語句,其作用是將攔截器責(zé)任鏈向后傳遞,本質(zhì)上便是動(dòng)態(tài)代理的invoke。

與常用插件的整合遇到的問題

pageHelper造成分頁失效的問題

通過查看pagehelper源碼,可以看到其inercept方法直接獲取了excutor然后開始分頁查詢,當(dāng)查詢到結(jié)果時(shí),便返回了。

就是pagehelper的intercept方法中沒有invocation.proceed(),這意味著什么?

//com.github.pagehelper.PageInterceptor#intercept
.....
? ? ? ? ? ? ? ? resultList = executor.query(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
? ? ? ? ? ? }
? ? ? ? ? ? return dialect.afterPage(resultList, parameter, rowBounds);
? ? ? ? } finally {
? ? ? ? ? ? dialect.afterAll();
? ? ? ? }

這意味著pagehelper沒有繼續(xù)向后傳遞責(zé)任鏈,而是自行處理直接返回。

由此,我們可以猜出該問題大概率與攔截器的執(zhí)行順序有關(guān)。

通過斷點(diǎn)調(diào)試,驗(yàn)證了該猜想,當(dāng)遇到分頁查詢時(shí),執(zhí)行到pagehelper就結(jié)束了,沒有進(jìn)入我們的自定義攔截器。這就可能造成我們自定義攔截器失效。

解決方案

因?yàn)镻ageHelper是Excetor類型的攔截器,所以我們?nèi)绻胍赑ageHelper攔截器前面執(zhí)行,就必須要將我們自己的攔截器添加到他的攔截器后面。

這里只介紹最簡(jiǎn)單最優(yōu)雅的一種方式:

注冊(cè)一個(gè)ApplicationListener監(jiān)聽器,監(jiān)聽 ContextRefreshedEvent 事件,當(dāng)所有的bean都初始化完成后(即PageHelper也已經(jīng)注冊(cè)好了),再把我們的自定義 MyBatis 攔截器注冊(cè)到 SqlSessionFactory 中。

可以提升的點(diǎn)

Interceptor接口提供了三個(gè)方法分別是攔截器處理邏輯的主要方法、判斷是否要進(jìn)行攔截,然后做出決定是否生成一個(gè)代理的方法及設(shè)置參數(shù)的方法。

package org.apache.ibatis.plugin;

import java.util.Properties;

public interface Interceptor {

? Object intercept(Invocation invocation) throws Throwable;

? default Object plugin(Object target) {
? ? return Plugin.wrap(target, this);
? }

? default void setProperties(Properties properties) {
? ? // NOP
? }
}

這里說的提升點(diǎn),就是在實(shí)現(xiàn)接口的實(shí)現(xiàn)類中,我們可以在plugin方法里加上一個(gè)判斷,因?yàn)槟J(rèn)情況下,攔截器根據(jù)順序攔截后,就可以去處理對(duì)應(yīng)邏輯了,這里加上一個(gè)判斷攔截的條件,可以減少代理類的創(chuàng)建。

? ? @Override
? ? public Object plugin(Object target) {
? ? ? ? if (target instanceof StatementHandler && checkIfNeeded((StatementHandler) target)) {
? ? ? ? ? ? return Plugin.wrap(target, this);
? ? ? ? } else {
? ? ? ? ? ? return target;
? ? ? ? }
? ? }

參考文檔:

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • MySQL優(yōu)化之分區(qū)表

    MySQL優(yōu)化之分區(qū)表

    這篇文章主要介紹了MySQL優(yōu)化之分區(qū)表,需要的朋友可以參考下
    2016-06-06
  • mysql 8.0.20 安裝配置詳細(xì)教程

    mysql 8.0.20 安裝配置詳細(xì)教程

    這篇文章主要為大家詳細(xì)介紹了mysql 8.0.20 安裝配置詳細(xì)教程,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • MySQL學(xué)習(xí)第二天 安裝和配置mysql winx64

    MySQL學(xué)習(xí)第二天 安裝和配置mysql winx64

    MySQL學(xué)習(xí)第二天,主要為大家詳細(xì)介紹了在Windows 64位操作系統(tǒng)下安裝和配置MySQL的具體步驟,整理一份mysql winx64安裝配置方法教程,感興趣的小伙伴們可以參考一下
    2016-05-05
  • Windows 8.1下MySQL5.7 忘記root 密碼的解決方法

    Windows 8.1下MySQL5.7 忘記root 密碼的解決方法

    最近學(xué)習(xí)碰到了一件挺令人尷尬的事情,我把MySQL的密碼給忘記了,所以MySQL登錄不進(jìn)去。在網(wǎng)上找的解決方案都不靠譜,下面小編給大家分享Windows 8.1下MySQL5.7 忘記root 密碼的解決方法,需要的朋友一起看看吧
    2017-07-07
  • linux下 root 登錄 MySQL 報(bào)錯(cuò)的問題

    linux下 root 登錄 MySQL 報(bào)錯(cuò)的問題

    本文給大家記錄的是個(gè)人在linux下使用root用戶登錄mysql的時(shí)候遇到的一個(gè)錯(cuò)誤的解決方法,非常的簡(jiǎn)單實(shí)用,有需要的小伙伴可以參考下。
    2016-02-02
  • 簡(jiǎn)述MySQL主鍵和外鍵使用及說明

    簡(jiǎn)述MySQL主鍵和外鍵使用及說明

    MySQL通過外鍵約束來保證表與表之間的數(shù)據(jù)的完整性和準(zhǔn)確性,本文主要介紹了簡(jiǎn)述MySQL主鍵和外鍵使用及說明,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • SQL Server服務(wù)器監(jiān)控

    SQL Server服務(wù)器監(jiān)控

    這篇文章主要介紹了SQL Server服務(wù)器監(jiān)控,SQL server監(jiān)控是收集、聚合和監(jiān)控SQL服務(wù)器的各種指標(biāo)的過程,更多相關(guān)內(nèi)容需要的朋友可以參考一下
    2022-09-09
  • mysql 分頁優(yōu)化解析

    mysql 分頁優(yōu)化解析

    似乎討論分頁的人很少,難道大家都沉迷于limit m,n?在有索引的情況下,limit m,n速度足夠,可是在復(fù)雜條件搜索時(shí),where somthing order by somefield+somefieldmysql會(huì)搜遍數(shù)據(jù)庫,找出“所有”符合條件的記錄,然后取出m,n條記錄。
    2008-04-04
  • MySQL insert into select 主鍵沖突解決方案

    MySQL insert into select 主鍵沖突解決方案

    本文主要介紹了MySQL insert into select主鍵沖突解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-06-06
  • mysql語法之DQL操作詳解

    mysql語法之DQL操作詳解

    大家好,本篇文章主要講的是mysql語法之DQL操作詳解,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01

最新評(píng)論

连山| 丹东市| 白水县| 阿巴嘎旗| 新田县| 辽中县| 柳林县| 刚察县| 东安县| 三原县| 蛟河市| 日照市| 综艺| 双流县| 信丰县| 肃北| 惠安县| 罗田县| 顺昌县| 墨竹工卡县| 龙胜| 丁青县| 乌鲁木齐县| 昂仁县| 张家川| 蒲城县| 马龙县| 南阳市| 阿拉善左旗| 陇西县| 库尔勒市| 阜康市| 宜州市| 仪陇县| 中阳县| 漯河市| 上林县| 温州市| 庆元县| 贵德县| 江华|