MyBatis Excutor 攔截器的巧妙用法
這里要講的巧妙用法是用來(lái)實(shí)現(xiàn)在攔截器中執(zhí)行額外 MyBatis 現(xiàn)有方法的用法。
并且會(huì)提供一個(gè)解決攔截Executor時(shí)想要修改MappedStatement時(shí)解決并發(fā)的問(wèn)題。
這里假設(shè)一個(gè)場(chǎng)景:
實(shí)現(xiàn)一個(gè)攔截器,記錄 MyBatis 所有的 insert,update,delete 操作,將記錄的信息存入數(shù)據(jù)庫(kù)。
這個(gè)用法在這里就是將記錄的信息存入數(shù)據(jù)庫(kù)。
實(shí)現(xiàn)過(guò)程的關(guān)鍵步驟和代碼:
1.首先在某個(gè) Mapper.xml 中定義好了一個(gè)往日志表中插入記錄的方法,假設(shè)方法為id="insertSqlLog"。
2.日志表相關(guān)的實(shí)體類(lèi)為SqlLog.
3.攔截器簽名:
@Intercepts({@org.apache.ibatis.plugin.Signature(
type=Executor.class,
method="update",
args={MappedStatement.class, Object.class})})
public class SqlInterceptor implements Interceptor
4.接口方法簡(jiǎn)單實(shí)現(xiàn):
public Object intercept(Invocation invocation) throws Throwable {
Object[] args = invocation.getArgs();
MappedStatement ms = (MappedStatement) args[0];
Object parameter = args[1];
SqlLog log = new SqlLog();
Configuration configuration = ms.getConfiguration();
Object target = invocation.getTarget();
StatementHandler handler = configuration.newStatementHandler((Executor) target, ms,
parameter, RowBounds.DEFAULT, null, null);
BoundSql boundSql = handler.getBoundSql();
//記錄SQL
log.setSqlclause(boundSql.getSql());
//執(zhí)行真正的方法
Object result = invocation.proceed();
//記錄影響行數(shù)
log.setResult(Integer.valueOf(Integer.parseInt(result.toString())));
//記錄時(shí)間
log.setWhencreated(new Date());
//TODO 還可以記錄參數(shù),或者單表id操作時(shí),記錄數(shù)據(jù)操作前的狀態(tài)
//獲取insertSqlLog方法
ms = ms.getConfiguration().getMappedStatement("insertSqlLog");
//替換當(dāng)前的參數(shù)為新的ms
args[0] = ms;
//insertSqlLog 方法的參數(shù)為 log
args[1] = log;
//執(zhí)行insertSqlLog方法
invocation.proceed();
//返回真正方法執(zhí)行的結(jié)果
return result;
}
重點(diǎn)
MappedStatement是一個(gè)共享的緩存對(duì)象,這個(gè)對(duì)象是存在并發(fā)問(wèn)題的,所以幾乎任何情況下都不能去修改這個(gè)對(duì)象(通用Mapper除外),想要對(duì)MappedStatement做修改該怎么辦呢?
并不難,Executor中的攔截器方法參數(shù)中都有MappedStatement ms,這個(gè)ms就是后續(xù)方法執(zhí)行要真正用到的MappedStatement,這樣一來(lái),問(wèn)題就容易解決了,根據(jù)自己的需要,深層復(fù)制MappedStatement對(duì)象中自己需要修改的屬性,然后修改這部分屬性,之后將修改后的ms通過(guò)上面代碼中args[0]=ms這種方式替換原有的參數(shù),這樣就能實(shí)現(xiàn)對(duì)ms的修改而且不會(huì)有并發(fā)問(wèn)題了。
這里日志的例子就是一個(gè)更簡(jiǎn)單的應(yīng)用,并沒(méi)有創(chuàng)建ms,只是獲取了一個(gè)新的ms替換現(xiàn)有的ms,然后去執(zhí)行。
總結(jié)
以上所述是小編給大家介紹的MyBatis Excutor 攔截器的巧妙用法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Java如何使用spire進(jìn)行word文檔的替換詳解
創(chuàng)作一份文案經(jīng)常會(huì)高頻率地使用某些詞匯,如地名、人名、人物職位等,若表述有誤,就需要整體撤換,下面這篇文章主要給大家介紹了關(guān)于Java如何使用spire進(jìn)行word文檔的替換的相關(guān)資料,需要的朋友可以參考下2023-01-01
Java通過(guò)正則表達(dá)式獲取字符串中數(shù)字的方法示例
最近工作中遇到了一個(gè)需求,需要利用java獲取字符串中的數(shù)字,嘗試幾種方法后發(fā)現(xiàn)利用正則表達(dá)式實(shí)現(xiàn)最為方法,下面這篇文章就主要介紹了Java通過(guò)正則表達(dá)式獲取字符串中數(shù)字的方法,文中給出了詳細(xì)的示例代碼,需要的朋友可以參考下。2017-03-03
在java中 利用匿名內(nèi)部類(lèi)進(jìn)行較簡(jiǎn)潔的雙括弧初始化的方法
本篇文章小編將為大家介紹,關(guān)于在java中 利用匿名內(nèi)部類(lèi)進(jìn)行較簡(jiǎn)潔的雙括弧初始化的方法,有需要的朋友可以參考一下2013-04-04
Java使用FTPClient類(lèi)讀寫(xiě)FTP
這篇文章主要為大家詳細(xì)介紹了Java使用FTPClient類(lèi)讀寫(xiě)FTP的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04
java實(shí)現(xiàn)字符串排列組合問(wèn)題
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)字符串排列組合問(wèn)題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
在java中main函數(shù)如何調(diào)用外部非static方法
這篇文章主要介紹了在java中main函數(shù)如何調(diào)用外部非static方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12
java實(shí)現(xiàn)識(shí)別二維碼圖片功能
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)識(shí)別二維碼圖片功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04

