真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Mybatis最硬核的API是什么

本篇內(nèi)容主要講解“Mybatis最硬核的API是什么”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Mybatis最硬核的API是什么”吧!

站在用戶的角度思考問(wèn)題,與客戶深入溝通,找到貴陽(yáng)網(wǎng)站設(shè)計(jì)與貴陽(yáng)網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站建設(shè)、成都網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、網(wǎng)絡(luò)空間、企業(yè)郵箱。業(yè)務(wù)覆蓋貴陽(yáng)地區(qū)。

1、Mybatis 架構(gòu)與核心API

不出意外的話,在后續(xù)源碼剖析相關(guān)文章中,我們會(huì)對(duì) Mybatis 的源碼進(jìn)行一次大掃蕩,一起挖掘每一處值得大家深入理解/記憶的知識(shí)點(diǎn)。而在本文中,我們主要先把 Mybatis 的架構(gòu)/層次鋪開,俯視 Mybatis 架構(gòu)的設(shè)計(jì)全貌,再把幾個(gè)硬核的 API 詳細(xì)消化。

整體順序脈絡(luò),希望讓你有所期待 ~

Mybatis最硬核的API是什么

我們先簡(jiǎn)單揭開 Mybatis 神秘的源碼包,

瞅瞅 Ta 大致目錄結(jié)構(gòu) :

Mybatis最硬核的API是什么

看,Mybatis 的源代碼包整齊劃一排在 org.apache.ibatis 目錄下,基本設(shè)計(jì)用途我簡(jiǎn)單梳理成上面這張圖,方便大家直觀理解,當(dāng)然只看源碼包目錄結(jié)構(gòu),難免會(huì)顯得枯燥無(wú)物,所以我們?cè)倏匆幌?,其?shí) Mybatis 的源碼包功能上可以是這么劃分:

Mybatis最硬核的API是什么

上圖讓我們對(duì) Mybatis 的架構(gòu)有了抽象的理解。

然而,實(shí)際上具體的職能分工,核心 API 的場(chǎng)景應(yīng)用,到底會(huì)是怎樣一套流程呈現(xiàn)呢?

看下面這幅功能架構(gòu)設(shè)計(jì),或許你能更好的理解。

Mybatis最硬核的API是什么

根據(jù) Mybatis 功能架構(gòu)我們劃分成三層

  • 接口層:該層提供一系列接口讓用戶直接參與使用,包含信息配置與實(shí)際數(shù)據(jù)操作調(diào)用。配置方式包括:基于 XML 配置方式、基于 Java API 配置方式兩種方式,用戶也可以通過(guò)接口層 API 對(duì)數(shù)據(jù)庫(kù)發(fā)起增刪改查等操作的請(qǐng)求, 本層接口會(huì)把接收到的調(diào)用請(qǐng)求交給數(shù)據(jù)處理層的構(gòu)件去處理。

  • 數(shù)據(jù)處理層:該層是 Mybatis 的核心層,負(fù)責(zé)數(shù)據(jù)處理,主要包括SQL 參數(shù)映射解析、SQL 語(yǔ)句的實(shí)際執(zhí)行、執(zhí)行結(jié)果集的映射處理等。

  • 框架支撐層:該層屬于 Mybatis 的后勤保障層,包括數(shù)據(jù)庫(kù)連接管理、事務(wù)把控管理、配置加載與緩存處理、日志處理、異常處理等,提供基礎(chǔ)支撐能力,保障上層的數(shù)據(jù)處理。

我們知道,Mybatis 框架讓用戶只需要提供配置信息,并且專注于 SQL 的編寫即可,對(duì)于連接管理數(shù)據(jù)庫(kù)/事務(wù),或?qū)嶋H的 SQL 參數(shù)映射/語(yǔ)句執(zhí)行/結(jié)果集映射等操作,作為用戶都并不需要操心和參與。

但是,好奇的我們其實(shí)想知道,Mybatis 核心部分的數(shù)據(jù)處理在整體流程中,是如何支撐用戶請(qǐng)求?同時(shí)各個(gè)構(gòu)件之間交互,又是怎樣流轉(zhuǎn)呢?

很巧,我這里有一張圖,介紹了整體流程:

Mybatis最硬核的API是什么

根據(jù)以上框架流程圖進(jìn)行講解

  • 創(chuàng)建配置并調(diào)用API:這一環(huán)節(jié)發(fā)生在應(yīng)用程序端,是開發(fā)人員在實(shí)際應(yīng)用程序中進(jìn)行的兩步操作,第一步創(chuàng)建核心配置文件 Configuration.xml 和映射文件 mapper.xml (通過(guò)注解方式也可創(chuàng)建以上兩種配置),準(zhǔn)備好基礎(chǔ)配置和 SQL 語(yǔ)句之后;第二步就是直接調(diào)用 Mybatis 框架中的數(shù)據(jù)庫(kù)操作接口。

  • 加載配置并初始化:Mybatis 框架會(huì)根據(jù)應(yīng)用程序端提供的核心配置文件與 SQL 映射文件的內(nèi)容,使用資源輔助類 Resources 把配置文件讀取成輸入流,然后通過(guò)對(duì)應(yīng)的解析器解析并封裝到 Configuration 對(duì)象和 MappedStatement 對(duì)象,最終把對(duì)象存儲(chǔ)在內(nèi)存之中。

  • 創(chuàng)建會(huì)話并接收請(qǐng)求:在 Mybatis 框架加載配置并初始化配置對(duì)象之后,會(huì)話工廠構(gòu)建器 SqlSessionFactoryBuilder 同時(shí)創(chuàng)建會(huì)話工廠 SqlSessionFactory,會(huì)話工廠會(huì)根據(jù)應(yīng)用程序端的請(qǐng)求,創(chuàng)建會(huì)話 SqlSession,以便應(yīng)用程序端進(jìn)行數(shù)據(jù)庫(kù)交互。

  • 處理請(qǐng)求:SqlSession 接收到請(qǐng)求之后,實(shí)際上并沒(méi)有進(jìn)行處理,而是把請(qǐng)求轉(zhuǎn)發(fā)給執(zhí)行器 Executor,執(zhí)行器再分派到語(yǔ)句處理器 StatementHandler ,語(yǔ)句處理器會(huì)結(jié)合參數(shù)處理器 ParameterHandler ,進(jìn)行數(shù)據(jù)庫(kù)操作(底層封裝了 JDBC Statement 操作)。

  • 返回處理結(jié)果:每個(gè)語(yǔ)句處理器 StatementHandler 處理完成數(shù)據(jù)庫(kù)操作之后,會(huì)協(xié)同 ResultSetHandler 以及類型處理器 TypeHandler ,對(duì)底層 JDBC 返回的結(jié)果集進(jìn)行映射封裝,最終返回封裝對(duì)象。

針對(duì)以上總體框架流程涉及到的這些硬核 API,下面我們逐個(gè)展開介紹,但不會(huì)詳細(xì)剖析源碼與原理,包括構(gòu)建細(xì)節(jié),因?yàn)檫@些我們?cè)诤罄m(xù)的源碼剖析章節(jié)中都會(huì)詳細(xì)分析。

Mybatis最硬核的API是什么

2、Configuration – 全局配置對(duì)象

對(duì)于 Mybatis 的全局配置對(duì)象 Configuration,我相信無(wú)論是初學(xué)者還是資深玩家,都不會(huì)陌生。整個(gè) Mybatis 的宇宙,都圍繞著 Configuration 轉(zhuǎn)。Configuration 對(duì)象的結(jié)構(gòu)和 config.xml 配置文件的內(nèi)容幾乎相同,涵蓋了properties (屬性),settings (設(shè)置),typeAliases (類型別名),typeHandlers (類型處理器),objectFactory (對(duì)象工廠),mappers (映射器)等等,之前我們有專門的一篇文章詳細(xì)進(jìn)行介紹,感興趣的朋友往上翻到目錄列表,找到 《Mybatis系列全解(四):全網(wǎng)最全!Mybatis配置文件XML全貌詳解》一文詳細(xì)品味一番吧。

Mybatis最硬核的API是什么

配置對(duì)象 Configuration 通過(guò)解析器 XMLConfigBuilder 進(jìn)行解析,把全局配置文件 Config.xml 與 映射器配置文件 Mapper.xml 中的配置信息全部構(gòu)建成完整的 Configuration 對(duì)象,后續(xù)我們?cè)创a分析時(shí)詳細(xì)剖析整個(gè)過(guò)程。

Mybatis最硬核的API是什么

3、Resources – 資源輔助類

我們知道,像 Configuration 和 Mapper 的配置信息存放在 XML 文件中,Mybatis 框架在構(gòu)建配置對(duì)象時(shí),必須先把 XML 文件信息加載成流,再做后續(xù)的解析封裝,而 Resources 作為資源的輔助類,恰恰干的就是這個(gè)活,無(wú)論是通過(guò)加載本地資源或是加載遠(yuǎn)程資源,最終都會(huì)通過(guò) 類加載器訪問(wèn)資源文件并輸出文件流。

Mybatis最硬核的API是什么

//加載核心配置文件
InputStream resourceAsStream = 
    Resources.getResourceAsStream("Config.xml");

Resources 實(shí)實(shí)在在提供了一系列方法分分鐘解決你的文件讀取加載問(wèn)題:

Mybatis最硬核的API是什么

Mybatis最硬核的API是什么

4、SqlSessionFactoryBuilder – 會(huì)話工廠構(gòu)建器

我們一撞見(jiàn) xxxBuilder ,就大致能知道它是某類對(duì)象的構(gòu)建器,這里 SqlSessionFactoryBuilder 也是一樣,它是 Mybatis 中的一個(gè)會(huì)話工廠構(gòu)建器,在資源輔助類 Resources 讀取到文件流信息之后,它負(fù)責(zé)解析文件流信息并構(gòu)建會(huì)話工廠 SqlSessionFactory。(解析的配置文件包含:全局配置 Configuration 與映射器 Mapper)

Mybatis最硬核的API是什么

在程序應(yīng)用端,我們一般使用 SqlSessionFactoryBuilder 直接構(gòu)建會(huì)話工廠:

// 獲得sqlSession工廠對(duì)象
SqlSessionFactory sqlSessionFactory = 
    new SqlSessionFactoryBuilder().build(resourceAsStream);

當(dāng)然,如果你集成了 Spring 框架的項(xiàng)目,則不需要自己手工去構(gòu)建會(huì)話工廠,直接在 Spring 配置文件中指定即可,例如指定一個(gè) bean 對(duì)象,id 是 sqlSessionFactory,而 class 類指定為 org.mybatis.spring.SqlSessionFactoryBean 。

SqlSessionFactoryBuilder 內(nèi)部通過(guò)解析器 XMLConfigBuilder 解析了文件流,同時(shí)封裝成為配置對(duì)象 Configuration ,再把 Configuration 對(duì)象進(jìn)行傳遞并構(gòu)建實(shí)例。

public SqlSessionFactory build(
    InputStream inputStream, 
    String environment, 
    Properties properties) {
   
     
      // 配置解析器解析
      XMLConfigBuilder parser = 
          new XMLConfigBuilder(
          	inputStream,environment, properties);
    
      // 最終實(shí)例會(huì)話工廠
      return build(parser.parse()); 
    
}

最終實(shí)例會(huì)話工廠,其實(shí) Mybatis 默認(rèn)實(shí)現(xiàn)是 new 了一個(gè)DefaultSqlSessionFactory 實(shí)例。

// 最終實(shí)例會(huì)話工廠
public SqlSessionFactory build(Configuration config) {
   
    return new DefaultSqlSessionFactory(config);
}

會(huì)話工廠構(gòu)建器 SqlSessionFactoryBuilder 應(yīng)用了構(gòu)建者模式,主要目的就是為了構(gòu)建 SqlSessionFactory 對(duì)象,以便后續(xù)生產(chǎn) SqlSession 對(duì)象,這個(gè)構(gòu)造器基本上算是 Mybatis 框架的入口構(gòu)建器,它提供了一系列多態(tài)方法 build(),支持用戶使用 XML 配置文件或 Java API (Properties)來(lái)構(gòu)建會(huì)話工廠 SqlSessionFactory 實(shí)例。

SqlSessionFactoryBuilder 的一生只為成就 SqlSessionFactory,當(dāng) SqlSessionFactory 一經(jīng)實(shí)例,SqlSessionFactoryBuilder 使命完成,便可消亡,便可被丟棄。

Mybatis最硬核的API是什么

因此 SqlSessionFactoryBuilder 實(shí)例的最佳作用域是 方法作用域(也就是局部方法變量)。 你可以重用 SqlSessionFactoryBuilder 來(lái)創(chuàng)建多個(gè) SqlSessionFactory 實(shí)例,但最好不要一直保留著它,以保證所有的 XML 解析資源可以被釋放給更重要的事情。

SqlSessionFactoryBuilder 中靈活構(gòu)建會(huì)話工廠的一系列接口:

Mybatis最硬核的API是什么

Mybatis最硬核的API是什么

5、SqlSessionFactory – 會(huì)話工廠

會(huì)話工廠 SqlSessionFactory 是一個(gè)接口,作用是生產(chǎn)數(shù)據(jù)庫(kù)會(huì)話對(duì)象 SqlSession ,有兩個(gè)實(shí)現(xiàn)類:

  • **DefaultSqlSessionFactory **(默認(rèn)實(shí)現(xiàn))

  • **SqlSessionManager **(僅多實(shí)現(xiàn)了一個(gè) Sqlsession 接口,已棄用)

在介紹會(huì)話工廠構(gòu)建器 SqlSessionFactoryBuilder 的時(shí)候,我們了解到構(gòu)建器默認(rèn)創(chuàng)建了 DefaultSqlSessionFactory 實(shí)例,并且會(huì)話工廠本身會(huì)綁定一個(gè)重要的屬性 Configuration 對(duì)象,在生產(chǎn)會(huì)話時(shí),最終也會(huì)把 Configuration 配置對(duì)象傳遞并設(shè)置到會(huì)話 SqlSession 上。

Mybatis最硬核的API是什么

會(huì)話工廠可以簡(jiǎn)單創(chuàng)建 SqlSession 實(shí)例:

// 創(chuàng)建 SqlSession 實(shí)例
SqlSession session = sqlSessionFactory.openSession();

會(huì)話工廠創(chuàng)建 SqlSession 時(shí),會(huì)綁定數(shù)據(jù)源、事務(wù)處理、執(zhí)行器等等,默認(rèn)會(huì)話工廠實(shí)現(xiàn)類 DefaultSqlSessionFactory 在創(chuàng)建會(huì)話對(duì)象時(shí),最終都會(huì)調(diào)用 openSessionFromDataSource 方法 ,即是如此實(shí)現(xiàn):

// 每一個(gè) openSession 最終都會(huì)調(diào)用此處
private SqlSession openSessionFromDataSource(
    ExecutorType execType, 
    TransactionIsolationLevel level, 
    boolean autoCommit) {
   
    
    // 環(huán)境配置
    final Environment environment = 
        configuration.getEnvironment();
    
    // 事務(wù)工廠
    final TransactionFactory transactionFactory = 
        getTransactionFactoryFromEnvironment(environment);
    
    // 事務(wù)
    Transaction tx =
        transactionFactory.newTransaction(
        environment.getDataSource(), 
        level, 
        autoCommit);
    
    // 執(zhí)行器
    final Executor executor = 
        configuration.newExecutor(tx, execType);
    
    // 最終生成會(huì)話
    return new DefaultSqlSession(
          configuration, executor, autoCommit);
    
  }

另外,會(huì)話工廠其實(shí)提供了一系列接口來(lái)靈活生產(chǎn)會(huì)話 SqlSession,你可以指定:

  • 事務(wù)處理:你希望在 session 作用域中使用/開啟事務(wù)作用域(也就是不自動(dòng)提交事務(wù)),還是使用自動(dòng)提交(auto-commit),sqlSession 默認(rèn)不提交事務(wù),對(duì)于增刪改操作時(shí)需要手動(dòng)提交事務(wù)。

  • 數(shù)據(jù)庫(kù)連接:你希望 MyBatis 幫你從已配置的數(shù)據(jù)源獲取連接,還是使用自己提供的連接,可以動(dòng)態(tài)創(chuàng)建數(shù)據(jù)源對(duì)象 Connection。

  • 執(zhí)行器類型:你希望指定某類執(zhí)行器來(lái)創(chuàng)建/執(zhí)行/預(yù)處理語(yǔ)句,可以有普通執(zhí)行器(SimpleExecutor),或復(fù)用執(zhí)行器(ReuserExecutor)、還是批量執(zhí)行器(BatchExecutor)等,下面介紹執(zhí)行器時(shí)會(huì)詳細(xì)說(shuō)明。

  • 事務(wù)隔離級(jí)別支持:支持 JDBC 的五個(gè)隔離級(jí)別(NONE、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ 和 SERIALIZABLE),對(duì)于事務(wù)相關(guān)的內(nèi)容,我們后續(xù) 《spring 系列全解》會(huì)詳細(xì)講,這里簡(jiǎn)單說(shuō)明一下就是事務(wù)隔離級(jí)別主要為了解決例如臟讀、不可重復(fù)讀、幻讀等問(wèn)題,使用不同的事務(wù)隔離級(jí)別勢(shì)必會(huì)導(dǎo)致不同的數(shù)據(jù)庫(kù)執(zhí)行效率,因此我們?cè)俨煌南到y(tǒng)/功能中,對(duì)隔離級(jí)別有不同的需求。

Mybatis最硬核的API是什么

SqlSessionFactory一旦被創(chuàng)建就應(yīng)該在 應(yīng)用的運(yùn)行期間一直存在,沒(méi)有任何理由丟棄它或重新創(chuàng)建另一個(gè)實(shí)例。 使用 SqlSessionFactory 的最佳實(shí)踐是在應(yīng)用運(yùn)行期間不要重復(fù)創(chuàng)建多次,多次重建 SqlSessionFactory 被視為一種代碼“壞習(xí)慣”。因此 SqlSessionFactory 的最佳作用域是 應(yīng)用作用域。 最簡(jiǎn)單的就是使用單例模式或者靜態(tài)單例模式。

請(qǐng)記住,創(chuàng)建 SqlSessionFactory ,一次就好!

每個(gè)數(shù)據(jù)庫(kù)對(duì)應(yīng)一個(gè) SqlSessionFactory 實(shí)例。SqlSessionFactory 一旦被創(chuàng)建, 它的生命周期應(yīng)該與應(yīng)用的生命周期相同。所以,如果你想連接兩個(gè)數(shù)據(jù)庫(kù),就需要?jiǎng)?chuàng)建兩個(gè) SqlSessionFactory 實(shí)例,每個(gè)數(shù)據(jù)庫(kù)對(duì)應(yīng)一個(gè);而如果是三個(gè)數(shù)據(jù)庫(kù),就需要三個(gè)實(shí)例,依此類推。

Mybatis最硬核的API是什么

Mybatis最硬核的API是什么

6、SqlSession – 會(huì)話

SqlSession 是一個(gè)接口,有兩個(gè)實(shí)現(xiàn)類:

  • DefaultSqlSession(默認(rèn)實(shí)現(xiàn))

  • SqlSessionManager(已棄用)

簡(jiǎn)單來(lái)說(shuō),通過(guò)會(huì)話工廠構(gòu)建出 SqlSession 實(shí)例之后,我們就可以進(jìn)行增刪改查了,默認(rèn)實(shí)例 DefaultSqlSession 提供了如此多的方法供用戶使用,有超過(guò)30個(gè):

Mybatis最硬核的API是什么

sqlSession 的方法除了 CURD,還提供了事務(wù)的控制例如提交/關(guān)閉/回滾等、提供了配置對(duì)象的獲取例如 getConfiguration()、提供了批量語(yǔ)句的執(zhí)行更新例如 flushStatements()、提供了緩存清除例如 clearCache() 、提供了映射器的使用 getMapper() 等等。

Mybatis最硬核的API是什么

對(duì)于客戶端應(yīng)用層面來(lái)說(shuō),熟悉 sqlSession 的 API 基本就可以任意操作數(shù)據(jù)庫(kù)了,不過(guò)我們希望想進(jìn)一步了解 sqlSession 內(nèi)部是如何執(zhí)行 sql 呢?其實(shí) sqlSession 是 Mybatis 中用于和數(shù)據(jù)庫(kù)交互的 頂層類,通常將它與本地線程 ThreadLocal 綁定,一個(gè)會(huì)話使用一個(gè) SqlSession,并且在使用完畢之后進(jìn)行 關(guān)閉。

之所以稱 SqlSession 為數(shù)據(jù)交互的 頂層類,是它其實(shí)沒(méi)有完成實(shí)質(zhì)的數(shù)據(jù)庫(kù)操作。根據(jù)之前的架構(gòu)設(shè)計(jì)流程我們已經(jīng)清晰的知道,SqlSession 對(duì)數(shù)據(jù)庫(kù)的操作都會(huì)轉(zhuǎn)發(fā)給具體的執(zhí)行器 Executor 來(lái)完成 ;當(dāng)然執(zhí)行器也是甩手掌柜,執(zhí)行器 Executor 會(huì)再分派給語(yǔ)句處理器 StatementHandler ,語(yǔ)句處理器會(huì)結(jié)合參數(shù)處理器 ParameterHandler ,共同完成最終的數(shù)據(jù)庫(kù)執(zhí)行處理操作(底層還是封裝了 JDBC Statement 操作)。并在每個(gè)語(yǔ)句處理器 StatementHandler 處理完成數(shù)據(jù)庫(kù)操作之后, 通過(guò)結(jié)果結(jié)處理器 ResultSetHandler 以及類型處理器 TypeHandler ,對(duì)底層 JDBC 返回的結(jié)果集進(jìn)行映射封裝,最終才返回預(yù)期的封裝對(duì)象。

關(guān)注以下圖示 sqlSession 紅色高亮位置,詳細(xì)描述了會(huì)話的實(shí)際執(zhí)行路徑:

Mybatis最硬核的API是什么

SqlSession 可以理解為一次數(shù)據(jù)庫(kù)會(huì)話,一次會(huì)話當(dāng)中既可以執(zhí)行一次 sql ,也允許你批量執(zhí)行多次,但是一旦會(huì)話關(guān)閉之后想要再執(zhí)行 sql,那就必須重新創(chuàng)建會(huì)話。

Mybatis最硬核的API是什么

每個(gè)線程都應(yīng)該有它自己的 SqlSession 實(shí)例,SqlSession 的實(shí)例不是線程安全的,因此是不能被共享的,所以它的最佳的作用域是 請(qǐng)求(request)或方法(method)作用域。 絕對(duì)不能將 SqlSession 實(shí)例的引用放在一個(gè)類的靜態(tài)域,甚至一個(gè)類的實(shí)例變量也不行。 也絕不能將 SqlSession 實(shí)例的引用放在任何類型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你現(xiàn)在正在使用一種 Web 框架,考慮將 SqlSession 放在一個(gè)和 HTTP 請(qǐng)求相似的作用域中。 換句話說(shuō),每次收到 HTTP 請(qǐng)求,就可以打開一個(gè) SqlSession,返回一個(gè)響應(yīng)后,就關(guān)閉它。 這個(gè)關(guān)閉操作很重要,為了確保每次都能執(zhí)行關(guān)閉操作,你應(yīng)該把這個(gè)關(guān)閉操作放到 finally 塊中。

Spring 集成 Mybatis 之后,通過(guò)依賴注入可以創(chuàng)建線程安全的、基于事務(wù)的 SqlSession ,并管理他們的生命周期,推薦搭配使用。

Mybatis最硬核的API是什么

7、Executor – 執(zhí)行器

Executor 是一個(gè)執(zhí)行器接口,是 Mybatis 的調(diào)度核心,它定義了一組管理 Statement 對(duì)象與獲取事務(wù)的方法,并負(fù)責(zé) SQL 語(yǔ)句的生成和一級(jí)/二級(jí)查詢緩存的維護(hù)等,SqlSessionFactory 在創(chuàng)建 SqlSession 時(shí)會(huì)同時(shí)創(chuàng)建執(zhí)行器,并指定執(zhí)行器類型,默認(rèn)使用 SimpleExecutor 。執(zhí)行器接口有5個(gè)子孫實(shí)現(xiàn)類,其中 BaseExecutor 是抽象類,另外4個(gè)子孫實(shí)現(xiàn)類分別是:SimpleExecutor 、BatchExecutor、ReuseExecutor、CachingExecutor。

Mybatis最硬核的API是什么

  • BaseExecutor:基礎(chǔ)執(zhí)行器(抽象類),對(duì)Executor接口進(jìn)行了基本實(shí)現(xiàn),為下一級(jí)實(shí)現(xiàn)類執(zhí)行器提供基礎(chǔ)支持。BaseExecutor 有三個(gè)子類分別是 SimpleExecutor、ResuseExecutor、BatchExecutor。

  • SimpleExecutor:普通執(zhí)行器,繼承 BaseExecutor 抽象類,是 MyBatis 中 默認(rèn)使用的執(zhí)行器. 每執(zhí)行一次 update 或 select ,就開啟一個(gè) Statement 對(duì)象,用完立刻關(guān)閉 Statement 對(duì)象。(可以是 Statement 或 PrepareStatement 對(duì)象)。

  • ReuseExecutor:復(fù)用執(zhí)行器,繼承 BaseExecutor 抽象類,這里的復(fù)用指的是重復(fù)使用 Statement . 它會(huì)在內(nèi)部利用一個(gè) Map 把創(chuàng)建的 Statement 都緩存起來(lái),每次在執(zhí)行一條 SQL語(yǔ) 句時(shí),它都會(huì)去判斷之前是否存在基于該 SQL 緩存的 Statement 對(duì)象,存在且之前緩存的 Statement 對(duì)象對(duì)應(yīng)的 Connection 還沒(méi)有關(guān)閉則會(huì)繼續(xù)使用之前的 Statement 對(duì)象,否則將創(chuàng)建一個(gè)新的 Statement 對(duì)象,并將其緩存起來(lái)。因?yàn)槊恳粋€(gè)新的 SqlSession 都有一個(gè)新的 Executor 對(duì)象,所以我們緩存在 ReuseExecutor 上的 Statement 的作用域是同一個(gè) SqlSession 。

  • BatchExecutor:批處理執(zhí)行器,繼承 BaseExecutor 抽象類,通過(guò)批量操作來(lái)提高性能,用于將多個(gè) sql 語(yǔ)句一次性輸送到數(shù)據(jù)庫(kù)執(zhí)行。由于內(nèi)部有緩存的實(shí)現(xiàn),所以使用完成后需要調(diào)用 flushStatements() 來(lái)清除緩存。

  • CachingExecutor: 緩存執(zhí)行器,繼承 BaseExecutor 抽象類,它為 Executor 對(duì)象增加了 二級(jí)緩存的相關(guān)功能,cachingExecutor 有一個(gè)重要屬性 delegate,即為委托的執(zhí)行器對(duì)象,可以是 SimpleExecutor、ReuseExecutor、BatchExecutor 中任意一個(gè)。CachingExecutor 在執(zhí)行數(shù)據(jù)庫(kù) update 操作時(shí),它直接調(diào)用 委托對(duì)象 delegate 的 update 方法;而執(zhí)行查詢時(shí),它會(huì)先從緩存中獲取查詢結(jié)果,存在就返回,不存在則委托 delegate 去數(shù)據(jù)庫(kù)取,然后存儲(chǔ)到緩存 cache 中。

Mybatis 在構(gòu)建 Configuration 配置類時(shí)默認(rèn)把 ExecutorType.SIMPLE作為執(zhí)行器類型,當(dāng)我們的會(huì)話工廠 DefaultSqlSessionFactory 開始生產(chǎn) SqlSession 會(huì)話時(shí),會(huì)同時(shí)構(gòu)建執(zhí)行器,此時(shí)就會(huì)依據(jù)配置類 Configuration 構(gòu)建時(shí)指定的執(zhí)行器類型來(lái)實(shí)例具體執(zhí)行器 ,流程如下:

// 1、Configuration配置類構(gòu)建時(shí)
// 指定了默認(rèn)執(zhí)行器類型為:普通執(zhí)行器
protected ExecutorType defaultExecutorType 
    = ExecutorType.SIMPLE;

// 2、Configuration配置類中
// 提供方法獲取默認(rèn)執(zhí)行器類型
public ExecutorType getDefaultExecutorType() {
   
    return defaultExecutorType;
}

// 3、會(huì)話工廠創(chuàng)建 SqlSession 實(shí)例時(shí)
SqlSession session = sqlSessionFactory.openSession();

// 4、openSession 實(shí)際邏輯
public SqlSession openSession() {
   
    return 
       openSessionFromDataSource(
           // 這里可就獲取了默認(rèn)執(zhí)行器
           configuration.getDefaultExecutorType(), 
           null, 
           false
        );
}

這里,肯定有人想知道,我們能否指定其它執(zhí)行器呢?

答案是:當(dāng)然可以,有兩種方式指定:

  • 第一種方式是通過(guò) Java API 指定,在開啟會(huì)話 openSession 時(shí)進(jìn)行指定。例如:

// 創(chuàng)建 SqlSession 實(shí)例
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.REUSE)
    
// ExecutorType是一個(gè)枚舉
// 有三個(gè)值SIMPLE, REUSE, BATCH
  • 另一種通過(guò) Configuration 配置方式來(lái)指定默認(rèn)執(zhí)行器類型。例如


    
	

對(duì)于第二種 settings 的配置方式,其實(shí)之前我們?cè)诮榻B Mybatis 的配置文件中已經(jīng)講過(guò),這里再簡(jiǎn)單說(shuō)明一下,像上面配置 settings 中的屬性 defaultExecutorType ,基本這些屬性都是 Mybatis 額外提供給我們靈活設(shè)置的,就算我們不設(shè)置 Mybatis 也會(huì)有默認(rèn)值,例如像 defaultExecutorType 的默認(rèn)值就是 SIMPLE。你看一下 Mybatis 在解析 Configuration 配置時(shí)的默認(rèn)構(gòu)建,就會(huì)明白:

解析 Configuration 的解析器(類與具體方法的代碼路徑):

org.apache.ibatis.builder.xml.XMLConfigBuilder#settingsElement

我們截取部分代碼邏輯,下面是設(shè)置默認(rèn)執(zhí)行器類型屬性 defaultExecutorType 的內(nèi)容:

// 配置文件解析器 
public class XMLConfigBuilder {
   
    
    // 最終解析到的 Configuration 對(duì)象
    protected final Configuration configuration;
    
    // 為 Configuration 對(duì)象設(shè)置屬性
    private void settingsElement(Properties props) {
   
        
        // 設(shè)置默認(rèn)執(zhí)行器類型,默認(rèn)是 SIMPLE
        configuration.setDefaultExecutorType(
            ExecutorType.valueOf(
                props.getProperty(
                    "defaultExecutorType", "SIMPLE")));
        
        // .... 當(dāng)然這里還有很多屬性設(shè)置
        // .... 只要你在中配置即可
    
    }
}

注意,到此我們知道可以根據(jù)業(yè)務(wù)需要指定執(zhí)行器類型,例如 SIMPLE(普通執(zhí)行器), REUSE(復(fù)用執(zhí)行器), BATCH(批處理執(zhí)行器)。

但是,有朋友就好奇了,那緩存執(zhí)行器 CachingExecutor 好像不見(jiàn)說(shuō)明呢?

確實(shí)如此,因?yàn)榫彺鎴?zhí)行器個(gè)其它三個(gè)執(zhí)行器還不太一樣,CachingExecutor 是需要我們開啟二級(jí)緩存才會(huì)有,這里大家先不要思考什么是一級(jí)緩存,什么二級(jí)緩存,后續(xù)我們有一文會(huì)詳細(xì)講緩存整個(gè)知識(shí)內(nèi)容。

大家先了解一個(gè)概念即可,就是 Mybatis 的一級(jí)緩存是默認(rèn)開啟的,不管你要不要,都會(huì)有一級(jí)緩存,而二級(jí)緩存呢,是默認(rèn)關(guān)閉的,但允許我們手工開啟。

對(duì)比開啟二級(jí)緩存前后,執(zhí)行器執(zhí)行的區(qū)別吧!

  • 不開啟二級(jí)緩存,執(zhí)行器執(zhí)行時(shí)

Mybatis最硬核的API是什么

  • 開啟二級(jí)緩存之后,執(zhí)行器執(zhí)行時(shí)

Mybatis最硬核的API是什么

其實(shí)我們實(shí)際操作數(shù)據(jù)庫(kù),不會(huì)直接接觸到執(zhí)行器 Executor ,不過(guò)我們確實(shí)可以了解一下基本的執(zhí)行原理,下面列出了執(zhí)行器接口提供的眾多重載方法,基本用于事務(wù)/緩存/數(shù)據(jù)庫(kù)管理與訪問(wèn),可以知道一下:

Mybatis最硬核的API是什么

到此,對(duì)于執(zhí)行器有了基本的認(rèn)識(shí),但是實(shí)際上,我們知道執(zhí)行器自身沒(méi)有去具體執(zhí)行 SQL 語(yǔ)句,而是分派到語(yǔ)句處理器 StatementHandler ,語(yǔ)句處理器會(huì)結(jié)合參數(shù)處理器 ParameterHandler ,最終進(jìn)行數(shù)據(jù)庫(kù)操作。

Mybatis最硬核的API是什么

8、StatementHandler – 語(yǔ)句處理器

StatementHandler 是一個(gè)語(yǔ)句處理器接口,它封裝了 JDBC Statement 操作,負(fù)責(zé)對(duì) JDBC Statement 的操作,如 設(shè)置參數(shù)、結(jié)果集映射,是實(shí)際跟數(shù)據(jù)庫(kù)做交互的一道。StatementHandler 語(yǔ)句處理器實(shí)例,是在執(zhí)行器具體執(zhí)行 CRUD 操作時(shí)構(gòu)建的,默認(rèn)使用 PrepareStatementHandler。語(yǔ)句處理器接口有5個(gè)子孫實(shí)現(xiàn)類,其中 BaseStatementHandler 是抽象類,另外4個(gè)子孫實(shí)現(xiàn)類分別是:SimpleStatementHandler、PrepareStatementHandler、CallableStatementHandler、RoutingStatementHandler。

Mybatis最硬核的API是什么

  • BaseStatementHandler:基礎(chǔ)語(yǔ)句處理器(抽象類),它基本把語(yǔ)句處理器接口的核心部分都實(shí)現(xiàn)了,包括配置綁定、執(zhí)行器綁定、映射器綁定、參數(shù)處理器構(gòu)建、結(jié)果集處理器構(gòu)建、語(yǔ)句超時(shí)設(shè)置、語(yǔ)句關(guān)閉等,并另外定義了新的方法 instantiateStatement 供不同子類實(shí)現(xiàn)以便獲取不同類型的語(yǔ)句連接,子類可以普通執(zhí)行 SQL 語(yǔ)句,也可以做預(yù)編譯執(zhí)行,還可以執(zhí)行存儲(chǔ)過(guò)程等。

  • SimpleStatementHandler:普通語(yǔ)句處理器,繼承 BaseStatementHandler 抽象類,對(duì)應(yīng) java.sql.Statement 對(duì)象的處理,處理普通的不帶動(dòng)態(tài)參數(shù)運(yùn)行的 SQL,即執(zhí)行簡(jiǎn)單拼接的字符串語(yǔ)句,同時(shí)由于 Statement 的特性,SimpleStatementHandler 每次執(zhí)行都需要編譯 SQL (注意:我們知道 SQL 的執(zhí)行是需要編譯和解析的)。

  • PreparedStatementHandler:預(yù)編譯語(yǔ)句處理器,繼承 BaseStatementHandler 抽象類,對(duì)應(yīng) java.sql.PrepareStatement 對(duì)象的處理,相比上面的普通語(yǔ)句處理器,它支持可變參數(shù) SQL 執(zhí)行,由于 PrepareStatement 的特性,它會(huì)進(jìn)行預(yù)編譯,在緩存中一旦發(fā)現(xiàn)有預(yù)編譯的命令,會(huì)直接解析執(zhí)行,所以減少了再次編譯環(huán)節(jié),能夠有效提高系統(tǒng)性能,并預(yù)防 SQL 注入攻擊(所以是系統(tǒng)默認(rèn)也是我們推薦的語(yǔ)句處理器)。

  • CallableStatementHandler:存儲(chǔ)過(guò)程處理器,繼承 BaseStatementHandler 抽象類,對(duì)應(yīng) java.sql.CallableStatement 對(duì)象的處理,很明了,它是用來(lái)調(diào)用存儲(chǔ)過(guò)程的,增加了存儲(chǔ)過(guò)程的函數(shù)調(diào)用以及輸出/輸入?yún)?shù)的處理支持。

其實(shí)普通語(yǔ)句處理器、預(yù)執(zhí)行語(yǔ)句處理器以及存儲(chǔ)過(guò)程處理器,只是 Mybatis 對(duì)于 JDBC 的語(yǔ)句執(zhí)行對(duì)象的簡(jiǎn)單包裝而已,沒(méi)有特別神秘,看以下 JDBC 的語(yǔ)句執(zhí)行對(duì)象的類圖關(guān)系也就能夠清楚。

  • RoutingStatementHandler:路由語(yǔ)句處理器,直接實(shí)現(xiàn)了 StatementHandler 接口,作用如其名稱,確確實(shí)實(shí)只是起到了路由功能,并把上面介紹到的三個(gè)語(yǔ)句處理器實(shí)例作為自身的委托對(duì)象而已,所以執(zhí)行器在構(gòu)建語(yǔ)句處理器時(shí),都是直接 new 了 RoutingStatementHandler 實(shí)例。

// 1、執(zhí)行器構(gòu)建語(yǔ)句處理器實(shí)例
public StatementHandler newStatementHandler(...) {
   
    
    // 構(gòu)建路由語(yǔ)句處理器即可!
    StatementHandler statementHandler = 
        new RoutingStatementHandler(...);
    
    // 其它邏輯忽略...
    return statementHandler;
}

// 2、實(shí)際構(gòu)造方法(路由關(guān)系)
public RoutingStatementHandler(...) {
   

    // 根據(jù)指定類型構(gòu)造委托實(shí)例
    switch (ms.getStatementType()) {
   
      case STATEMENT:
        delegate = new SimpleStatementHandler(...);
        break;
      case PREPARED:
        delegate = new PreparedStatementHandler(...);
        break;
      case CALLABLE:
        delegate = new CallableStatementHandler(...);
        break;
      default:
        throw new ExecutorException(
            "Unknown statement type: " 
                + ms.getStatementType());
    }
}

我們前面介紹了執(zhí)行器具體執(zhí)行 CRUD 操作時(shí),構(gòu)造的語(yǔ)句處理器默認(rèn)使用 PrepareStatementHandler ,不過(guò)有些好奇的腦袋就想問(wèn)問(wèn),那我們能不能指定語(yǔ)句處理器類型呢?

當(dāng)然可以,例如我們指定更新用戶語(yǔ)句適用預(yù)編譯處理語(yǔ)句處理器:



    update t_user set name = #{newName}

當(dāng) Mybatis 在解析映射器中的每條語(yǔ)句時(shí),會(huì)設(shè)置語(yǔ)句處理器類型:

// 語(yǔ)句對(duì)象解析器 
public class XMLStatementBuilder {
   
    
    // 解析語(yǔ)句節(jié)點(diǎn)
    public void parseStatementNode() {
    
        
        // 設(shè)置語(yǔ)句處理器類型
        // 默認(rèn)是 PREPARED 類型
        StatementType statementType = 
         StatementType.valueOf(
            context.getStringAttribute(
                "statementType", 
                StatementType.PREPARED.toString()
            )
        ); 
    }  
}

所以,語(yǔ)句執(zhí)行器與數(shù)據(jù)庫(kù)的交互過(guò)程:

Mybatis最硬核的API是什么

當(dāng)然,語(yǔ)句處理器接口 StatementHandler 提供了基本接口,一般我們沒(méi)必要自定義實(shí)現(xiàn)類,所以可以簡(jiǎn)單看一下即可:

Mybatis最硬核的API是什么

Mybatis最硬核的API是什么

9、ParamerHandler – 參數(shù)處理器

ParameterHandler 是一個(gè)參數(shù)處理器接口,它負(fù)責(zé)把用戶傳遞的參數(shù)轉(zhuǎn)換成 JDBC Statement 所需要的參數(shù),底層做數(shù)據(jù)轉(zhuǎn)換的工作會(huì)交給類型轉(zhuǎn)換器 TypeHandler,后面會(huì)介紹。

很顯然,需要對(duì)傳入的參數(shù)進(jìn)行轉(zhuǎn)換處理的 StatementHandler 實(shí)例只有兩個(gè),分別是:

  • PrepareStatementHandler預(yù)編譯處理器

  • CallableStatementHandler存儲(chǔ)過(guò)程處理器

上面在介紹語(yǔ)句處理器的時(shí)候,我們有介紹說(shuō)基礎(chǔ)語(yǔ)句處理器 BaseStatementHandler 在進(jìn)行實(shí)例構(gòu)建時(shí),會(huì)同時(shí)構(gòu)建參數(shù)處理器與結(jié)果集處理器,所以參數(shù)處理器就是在此時(shí)被構(gòu)建。

// 基礎(chǔ)語(yǔ)句處理器
public abstract class BaseStatementHandler{
   
    
    // 構(gòu)造實(shí)例時(shí)
    protected BaseStatementHandler(...){
   
        
        // 其它邏輯可忽略...
        
        // 1、構(gòu)建參數(shù)處理器
        this.parameterHandler = 
            conf.newParameterHandler(...);
    	
        // 2、構(gòu)建結(jié)果集處理器
        this.resultSetHandler = 
        	conf.newResultSetHandler(...);
    } 
}

對(duì)于參數(shù)處理器接口,相對(duì)簡(jiǎn)單,只有1個(gè)默認(rèn)實(shí)現(xiàn)類 DefaultParameterHandler ,該接口只有兩個(gè)方法,分別是:

Mybatis最硬核的API是什么

  • 1、setParameters設(shè)置參數(shù),發(fā)生在 CURD 語(yǔ)句執(zhí)行時(shí),語(yǔ)句處理器設(shè)置參數(shù)

// 有2個(gè)處理器會(huì)使用,分別是:
// 預(yù)編譯處理器 PreparedStatementHandler
// 存儲(chǔ)過(guò)程處理器 CallableStatementHandler

public void parameterize(Statement statement) {
   
    
    //使用ParameterHandler對(duì)象來(lái)完成對(duì)Statement的設(shè)值
    parameterHandler.setParameters(statement);
}

應(yīng)用場(chǎng)景例如查詢用戶對(duì)象時(shí),設(shè)置姓名,參數(shù)處理器結(jié)合類型處理器把 name 屬性占位符進(jìn)行賦值。


    select * from t_user where name = #{name}
  • 2、getParameterObject獲取參數(shù),發(fā)生在結(jié)果集返回時(shí),結(jié)果集處理器獲取對(duì)象參數(shù),值得注意的時(shí),該方法只用于存儲(chǔ)過(guò)程處理器 CallableStatementHandler 。

// 默認(rèn)結(jié)果集處理器
public class DefaultResultSetHandler{
   
   
    // 處理輸出參數(shù)
    public void handleOutputParameters(...) {
   
    
        // 獲取參數(shù)
        final Object parameterObject = 
            parameterHandler.getParameterObject();
    
    	// 其它存儲(chǔ)過(guò)程輸出參數(shù)處理邏輯...
	}    
}

Mybatis最硬核的API是什么

10、ResultSetHandler – 結(jié)果集處理器

ResultSetHandler 是一個(gè)結(jié)果集處理器接口,它負(fù)責(zé)負(fù)責(zé)將 JDBC 返回的結(jié)果集 resultSet 對(duì)象轉(zhuǎn)換為 List 類型的集合,是在語(yǔ)句處理器構(gòu)建實(shí)例時(shí)被同時(shí)創(chuàng)建,底層做數(shù)據(jù)轉(zhuǎn)換的工作會(huì)交給類型轉(zhuǎn)換器 TypeHandler,它有1個(gè)默認(rèn)實(shí)現(xiàn)類 DefaultResultSetHandler,該接口有3個(gè)方法,分別是:

Mybatis最硬核的API是什么

  • handleResultSets:負(fù)責(zé)結(jié)果集處理,完成映射返回結(jié)果對(duì)象

  • handleCursorResultSets:負(fù)責(zé)游標(biāo)對(duì)象處理

  • handleOutputParameters:負(fù)責(zé)存儲(chǔ)過(guò)程的輸出參數(shù)處理

結(jié)果集處理器對(duì)于 JDBC 返回的結(jié)果集的基本處理,是先獲取我們?cè)谟成淦?Mapper 中指定 resultType 或 resultMap 映射關(guān)系,然后遍歷解析結(jié)果集中的每一列數(shù)據(jù),底層通過(guò) MetaObject 對(duì)象做相關(guān)的反射處理。

對(duì)于詳細(xì)的源碼邏輯,我們后續(xù)源碼剖析部分詳細(xì)講。

不講不是中國(guó)人 O(∩_∩)O ~

Mybatis最硬核的API是什么

11、TypeHandler – 類型轉(zhuǎn)換器

TypeHandler 是一個(gè)類型轉(zhuǎn)換器/處理器接口,它負(fù)責(zé) Java 數(shù)據(jù)類型和 JDBC 數(shù)據(jù)類型之間的映射與轉(zhuǎn)換,當(dāng)對(duì) Statement 對(duì)象設(shè)置參數(shù)時(shí),由 JavaType 轉(zhuǎn)換為 JdbcType,當(dāng)對(duì) Statement 返回結(jié)果集進(jìn)行封裝映射時(shí),又會(huì)將 JdbcType 轉(zhuǎn)換為 JavaType。

Mybatis最硬核的API是什么

一般,我們可以直接使用 Mybatis 內(nèi)置的類型處理器,簡(jiǎn)單看了一下有 65+ 個(gè),當(dāng)然我們是可以根據(jù)業(yè)務(wù)需要自定義類型處理器的,以便處理復(fù)雜類型或非標(biāo)類型。

具體做法為:

1、實(shí)現(xiàn) org.apache.ibatis.type.TypeHandler 接口;

2、繼承 org.apache.ibatis.type.BaseTypeHandler 類。

其中 BaseTypeHandler 類作為抽象類就已經(jīng)實(shí)現(xiàn)了 TypeHandler 接口。

我們看到接口 TypeHandler 定義了四個(gè)方法:

public interface TypeHandler {
   

  // 設(shè)置參數(shù)
  void setParameter(
      PreparedStatement ps, 
      int i, T parameter, 
      JdbcType jdbcType);

  // 根據(jù)列名獲取轉(zhuǎn)換結(jié)果
  T getResult(ResultSet rs, String columnName);

  // 根據(jù)列下標(biāo)獲取轉(zhuǎn)換結(jié)果
  T getResult(ResultSet rs, int columnIndex);

  // 根據(jù)列下標(biāo)獲取【存儲(chǔ)過(guò)程】的輸出結(jié)果
  T getResult(CallableStatement cs, int columnIndex);

}

其實(shí),我之前在介紹 Mybatis 核心配置的時(shí)候,有大力介紹過(guò)類型處理器,沒(méi)必要重復(fù)寫(其實(shí)是懶),感興趣的朋友可以直接看我們之前的文章 **《Mybatis系列全解(四):全網(wǎng)最全!Mybatis配置文件XML全貌詳解》**中對(duì)類型處理器 TypeHandler 的介紹。

Mybatis最硬核的API是什么

12、MappedStatement – 語(yǔ)句對(duì)象

MappedStatement 語(yǔ)句對(duì)象,就是我們?cè)谟成淦?Mapper 中維護(hù)的每一條語(yǔ)句,例如 ,Mybatis 中通過(guò)語(yǔ)句構(gòu)造器 XMLStatementBuilder 對(duì)每一個(gè)語(yǔ)句進(jìn)行解析:

Mybatis最硬核的API是什么

整個(gè)解析過(guò)程分為4步驟:

  • 1、配置解析器 XMLConfigBuilder 解析映射器:

// Configuration 配置解析器
public class XMLConfigBuilder{
   
    
    // 解析映射器
    private void mapperElement(){
   
        
        // 創(chuàng)建映射器解析實(shí)例
        XMLMapperBuilder mapperParser = 
            new XMLMapperBuilder(...);
        
        // 開始解析
        mapperParser.parse();
    }
}

2、映射對(duì)象解析器 XMLMapperBuilder 解析語(yǔ)句

// 映射對(duì)象解析器
public class XMLMapperBuilder{
   
    
    // 1、解析入口
    public void parse() {
    
        
        // 解析映射器文件
        configurationElement(
            parser.evalNode("/mapper"));
    }
    
    // 2、節(jié)點(diǎn)解析
    private void configurationElement(XNode context) {
   
        
        // 構(gòu)建語(yǔ)句對(duì)象
        buildStatementFromContext(
            context.evalNodes(
                "select|insert|update|delete"));
    }
    
    // 3、最終調(diào)用語(yǔ)句解析器
    private void buildStatementFromContext(){
   
        
        // 創(chuàng)建語(yǔ)句解析實(shí)例
        XMLStatementBuilder statementParser = 
            new XMLStatementBuilder();
        
        // 解析語(yǔ)句節(jié)點(diǎn)
        statementParser.parseStatementNode();
    }
}

3、語(yǔ)句解析器 XMLStatementBuilder 解析每一個(gè)節(jié)點(diǎn)

// 語(yǔ)句解析器
public class XMLStatementBuilder{
   
    
    // 解析語(yǔ)句節(jié)點(diǎn)
    public void parseStatementNode() {
   
        
        // 通過(guò)語(yǔ)句輔助類構(gòu)建語(yǔ)句對(duì)象
        builderAssistant.addMappedStatement(...)
    }
}

4、語(yǔ)句輔助類 MapperBuilderAssistant 添加進(jìn)語(yǔ)句集合中

// 語(yǔ)句輔助類
public class MapperBuilderAssistant{
   
    
    // 添加語(yǔ)句對(duì)象
    public MappedStatement addMappedStatement(
         
        // 最終添加到配置類的語(yǔ)句集合中
    	configuration.addMappedStatement(statement);
    }
}

Mybatis最硬核的API是什么

13、SqlSource – SQL源

SqlSource 是一個(gè) SQL 源接口,它會(huì)結(jié)合用戶傳遞的參數(shù)對(duì)象 parameterObject,動(dòng)態(tài)地生成 SQL 語(yǔ)句,并最終封裝成 BoundSql 對(duì)象。SqlSource 接口有5個(gè)實(shí)現(xiàn)類,分別是:StaticSqlSource、DynamicSqlSource、RawSqlSource、ProviderSqlSource、VelocitySqlSource(這只是一個(gè)測(cè)試用例,而非真正模板 Sql 源實(shí)現(xiàn)類)。

Mybatis最硬核的API是什么

  • StaticSqlSource:靜態(tài) SQL 源實(shí)現(xiàn)類,所有的 SQL 源最終都會(huì)構(gòu)建 StaticSqlSource 實(shí)例,該實(shí)現(xiàn)類會(huì)生成最終可執(zhí)行的 SQL 語(yǔ)句供 statement 或 prepareStatement 使用。

  • RawSqlSource:原生 SQL 源實(shí)現(xiàn)類,解析構(gòu)建含有 ‘#{}’ 占位符的 SQL 語(yǔ)句或原生 SQL 語(yǔ)句,解析完最終會(huì)構(gòu)建 StaticSqlSource 實(shí)例。

  • DynamicSqlSource:動(dòng)態(tài) SQL 源實(shí)現(xiàn)類,解析構(gòu)建含有 ‘${}’ 替換符的 SQL 語(yǔ)句或含有動(dòng)態(tài) SQL 的語(yǔ)句(例如 If/Where/Foreach等),解析完最終會(huì)構(gòu)建 StaticSqlSource 實(shí)例。

  • ProviderSqlSource:注解方式的 SQL 源實(shí)現(xiàn)類,會(huì)根據(jù) SQL 語(yǔ)句的內(nèi)容分發(fā)給 RawSqlSource 或 DynamicSqlSource ,當(dāng)然最終也會(huì)構(gòu)建 StaticSqlSource 實(shí)例。

  • VelocitySqlSource:模板 SQL 源實(shí)現(xiàn)類,官方申明這只是一個(gè)測(cè)試用例,而非真正的模板 Sql 源實(shí)現(xiàn)類。

SqlSource 實(shí)例在配置類 Configuration 解析階段就被創(chuàng)建,Mybatis 框架會(huì)依據(jù)3個(gè)維度的信息來(lái)選擇構(gòu)建哪種數(shù)據(jù)源實(shí)例:

  • 第一個(gè)維度:客戶端的 SQL 配置方式:XML 方式或者注解方式。

  • 第二個(gè)維度:SQL 語(yǔ)句中是否使用動(dòng)態(tài) SQL ( if/where/foreach 等 )。

  • 第三個(gè)維度:SQL 語(yǔ)句中是否含有替換符 ‘${}’ 或占位符 ‘#{}’ 。

SqlSource 接口只有一個(gè)方法 getBoundSql ,就是創(chuàng)建 BoundSql 對(duì)象。

public interface SqlSource {
   

  BoundSql getBoundSql(Object parameterObject);

}

Mybatis最硬核的API是什么

14、BoundSql – SQL語(yǔ)句

BoundSql 對(duì)象存儲(chǔ)了動(dòng)態(tài)生成的 SQL 語(yǔ)句以及相應(yīng)的參數(shù)信息,BoundSql 對(duì)象是在執(zhí)行器具體執(zhí)行 CURD 時(shí)通過(guò)實(shí)際的 SqlSource 實(shí)例所構(gòu)建。通過(guò) BoundSql 能夠獲取到實(shí)際數(shù)據(jù)庫(kù)執(zhí)行的 SQL 語(yǔ)句,系統(tǒng)可根據(jù) SQL 語(yǔ)句構(gòu)建 Statement 或者 PrepareStatement 。

public class BoundSql {
   

  //該字段中記錄了SQL語(yǔ)句,該SQL語(yǔ)句中可能含有"?"占位符
  private final String sql;
    
  //SQL中的參數(shù)屬性集合
  private final List parameterMappings;
    
  //客戶端執(zhí)行SQL時(shí)傳入的實(shí)際參數(shù)值
  private final Object parameterObject;
    
  //復(fù)制 DynamicContext.bindings 集合中的內(nèi)容
  private final Map additionalParameters;
    
  //通過(guò) additionalParameters 構(gòu)建元參數(shù)對(duì)象
  private final MetaObject metaParameters;
    
}

到此,相信大家對(duì)“Mybatis最硬核的API是什么”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!


當(dāng)前名稱:Mybatis最硬核的API是什么
轉(zhuǎn)載注明:http://weahome.cn/article/ggiegh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部