一 執(zhí)行器層次結(jié)構(gòu)
mybatis 大體上的執(zhí)行器關(guān)系鏈路如圖咐蝇。上層的 CachingExecutor 和 BaseExecutor 各自處理一級(jí)緩存特姐。
最基礎(chǔ)的三個(gè)執(zhí)行器負(fù)責(zé)與數(shù)據(jù)庫(kù)交互。并且三者之間各有區(qū)別炒辉。
1.1 SimpleExecutor
最基礎(chǔ)的簡(jiǎn)單執(zhí)行器
org.apache.ibatis.executor.SimpleExecutor
當(dāng)我們使用 mybatis 封裝好的 sqlSession 會(huì)話來(lái)進(jìn)行數(shù)據(jù)庫(kù)交互的時(shí)候豪墅,debug 代碼,就會(huì)發(fā)現(xiàn)底層的調(diào)用黔寇,默認(rèn)就是執(zhí)行到了
org.apache.ibatis.executor.SimpleExecutor#doQuery
一次查詢(xún)操作在基礎(chǔ)執(zhí)行器中的流程邏輯是:
- 根據(jù) mybatis 配置的 sql 全局 id 和 sql 語(yǔ)句的映射實(shí)體對(duì)象 mappedStatement 來(lái)獲取一個(gè)配置類(lèi)實(shí)體偶器。這個(gè)配置類(lèi)包含了環(huán)境配置/指定執(zhí)行器類(lèi)型/日志配置等等
- 創(chuàng)建一個(gè) statement 處理器,包含了語(yǔ)句映射關(guān)系/分頁(yè)參數(shù)/前面創(chuàng)建的配置類(lèi)引用等等
- 預(yù)編譯 sql 語(yǔ)句
- 執(zhí)行查詢(xún)操作
每次調(diào)用簡(jiǎn)單執(zhí)行器的查詢(xún)動(dòng)作,都會(huì)執(zhí)行完整的 sql 預(yù)編譯過(guò)程屏轰,即這個(gè)方法:
org.apache.ibatis.executor.SimpleExecutor#prepareStatement
這是一個(gè)細(xì)微的性能損耗優(yōu)化點(diǎn)颊郎。使用另一個(gè)基類(lèi)執(zhí)行器 ReuseExecutor 可以避免重復(fù)預(yù)編譯完全一樣的 sql,當(dāng)然這個(gè)優(yōu)化范圍也是在 同一個(gè) session 域內(nèi)霎苗。
1.2 ReuseExecutor
復(fù)用執(zhí)行器
org.apache.ibatis.executor.ReuseExecutor
這里的 復(fù)用 指的是對(duì) sql 語(yǔ)句預(yù)編譯動(dòng)作的復(fù)用姆吭。執(zhí)行器內(nèi)會(huì)緩存預(yù)編譯通過(guò)的 sql,并在接到相同的 sql 和執(zhí)行請(qǐng)求的時(shí)候唁盏,從本地緩存中檢索出之前已經(jīng)執(zhí)行過(guò)的內(nèi)容并執(zhí)行内狸。這樣就可以省略預(yù)編譯過(guò)程的性能損耗。
本地緩存厘擂,是一個(gè) hashmap 結(jié)構(gòu):
private final Map<String, Statement> statementMap = new HashMap<>();
保存的鍵值對(duì)就是 sql-stmt 的映射關(guān)系集合昆淡。
mybatis 默認(rèn)使用的底層執(zhí)行器是 SimpleExecutor,如果想要使用 ReuseExecutor刽严,需要在配置文件中新增配置昂灵,指定使用的執(zhí)行器。
1.3 BatchExecutor
批處理執(zhí)行器
org.apache.ibatis.executor.BatchExecutor
用于一次性操作更新大量數(shù)據(jù)的場(chǎng)景舞萄。批處理執(zhí)行器在用戶(hù)查詢(xún)場(chǎng)景的時(shí)候眨补,預(yù)編譯和 simpleExecutor 是沒(méi)有差別的。
注意批處理操作必須手動(dòng)處理/提交事物倒脓。