欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Mybatis的核心架構(gòu)及源碼解讀

 更新時(shí)間:2023年08月25日 09:58:52   作者:摳腳的大灰狼  
這篇文章主要介紹了Mybatis的核心架構(gòu)及源碼解讀,mybatis是一款半自動(dòng)化的持久層框架,它封裝了JDBC操作,支持定制化SQL,高級(jí)映射,但它的數(shù)據(jù)庫(kù)無關(guān)性較低,需要的朋友可以參考下

概述

mybatis是什么?

mybatis是一款半自動(dòng)化的持久層框架,它封裝了JDBC操作,支持定制化SQL,高級(jí)映射。但它的數(shù)據(jù)庫(kù)無關(guān)性較低,2個(gè)不同的數(shù)據(jù)庫(kù),可能需要2套SQL語句

mybatis的基本使用?

  • 編寫全局配置文件
  • 編寫mapper映射文件
  • 加載配置文件,生成SqlSessionFactory
  • 創(chuàng)建SqlSession,通過SqlSession調(diào)用mapper映射文件中的SQL語句來執(zhí)行數(shù)據(jù)庫(kù)操作

架構(gòu)流程

三層結(jié)構(gòu)

[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-LfGIOhPg-1573726013288)(C:\Users\Vergi\Desktop\3level-architech.png)]

接口層

使用SqlSession和Mapper接口,來完成對(duì)SQL語句的調(diào)用,日常開發(fā)中主要接觸這一層

數(shù)據(jù)處理層

這一層是mybatis進(jìn)行的工作,負(fù)責(zé)SQL語句組裝,查詢參數(shù)綁定,結(jié)果集映射

基礎(chǔ)支撐層

這一層可以理解為我們?nèi)峙渲美锏膬?nèi)容。包括數(shù)據(jù)庫(kù)連接信息,事務(wù)管理信息,配置緩存,編寫mapper映射文件中的SQL語句等

工作流程

  • 向SqlSession傳入SQL語句的id,以及查詢參數(shù)
  • 找到待執(zhí)行的SQL信息,交給Executor執(zhí)行器處理
  • Executor負(fù)責(zé)對(duì)SQL語句進(jìn)行組裝拼接,后交給StatementHandler處理
  • StatementHandler封裝了JDBC的操作,它負(fù)責(zé)根據(jù)SQL信息,生成對(duì)應(yīng)的Statement,并利用ParameterHandler進(jìn)行查詢參數(shù)的解析與綁定,后執(zhí)行查詢
  • StatemenHandler查詢完畢,將結(jié)果集交由ResultSetHandler進(jìn)行結(jié)果集信息的解析與封裝處理(參數(shù)解析,結(jié)果集解析,都會(huì)用TypeHandler來做類型轉(zhuǎn)換,java類型與JDBC類型)

源碼部分

全局配置文件解析過程

  • 獲得配置文件的InputStream,創(chuàng)建Document對(duì)象
  • 利用Xpath語法,解析各個(gè)配置節(jié)點(diǎn)
  • 將信息封裝到Configuration對(duì)象中,生成SqlSessionFactory

源碼過程

SqlSessionFactoryBuilder # build 
 |- XMLConfigBuilder # parse 
   |- XMLConfigBuilder # parseConfiguration

mapper映射文件解析過程

  • 一個(gè)mapper.xml映射文件,由namespace屬性作為唯一標(biāo)識(shí)
  • 擁有namespace屬性的mapper.xml映射文件,會(huì)被注冊(cè)到Configuration中的mapperRegistry中,以便后續(xù)生成mapper代理對(duì)象
  • 一個(gè)mapper.xml,對(duì)應(yīng)一個(gè)MapperBuilderAssistant對(duì)象,這個(gè)builderAssistant對(duì)象解析并保存了該mapper.xml中的公共標(biāo)簽,如parameterMap,resultMap,cache,sql,這些標(biāo)簽可能在某個(gè)CRUD標(biāo)簽里被使用
  • 解析CRUD標(biāo)簽,即 select | update | insert | delete 標(biāo)簽,一個(gè)CRUD標(biāo)簽,被封裝成一個(gè)MappedStatement對(duì)象,以標(biāo)簽的id屬性作為唯一標(biāo)識(shí),MappedStatement里包含了SQL語句信息,參數(shù)映射信息,結(jié)果集映射信息

源碼過程

XMLConfigBuilder # mapperElement
 |- XMLMapperBuilder # parse
   |- XMLMapperBuilder # configurationElement

SQL加載與組裝過程

SQL裝載

  • 在解析mapper映射文件中的CRUD標(biāo)簽時(shí),對(duì)SQL語句進(jìn)行了解析和封裝
  • 將一個(gè)CRUD標(biāo)簽,封裝成SqlNode,并將其子元素(可能是文本節(jié)點(diǎn),也可能是動(dòng)態(tài)SQL節(jié)點(diǎn)),也封裝成SqlNode,利用組合模式,對(duì)這些SqlNode進(jìn)行組裝,最終將SqlNode和Configuration封裝在一起,形成SqlSource
  • 有動(dòng)態(tài)SQL標(biāo)簽的,或者有${} 的,會(huì)被封裝成DynamicSqlSource,其余的,會(huì)被封裝成RawSqlSource(在Executor執(zhí)行時(shí)都會(huì)解析并封裝成StaticSqlSource)
  • SqlSource和其他信息,一起被封裝為MapperStatement,一個(gè)CRUD標(biāo)簽,對(duì)應(yīng)一個(gè)MappedStatement

源碼過程

XMLMapperBuilder # buildStatementFromContext
 |- XMLStatementBuilder # parseStatementNode
   |- XMLLanguageDriver # createSqlSource 
     |- XMLScriptBuilder # parseScriptNode

SQL組裝

  • 調(diào)用Executor進(jìn)行執(zhí)行時(shí),會(huì)查找對(duì)應(yīng)的MappedStatement,并調(diào)用其SqlSource的getBoundSql,進(jìn)行SQL語句的組裝,并封裝查詢參數(shù)
  • 調(diào)用getBoundSql方法時(shí),會(huì)調(diào)用SqlNode的apply方法,不同SqlNode子類,會(huì)采取不同方式,解析動(dòng)態(tài)SQL標(biāo)簽,并進(jìn)行SQL語句拼接,并將#{}替換為 ? ,將${}做字符串拼接,之后封裝到StaticSqlSource,此時(shí)已經(jīng)將SQL語句解析并組裝,這個(gè)StaticSqlSource里就是SQL語句以及查詢參數(shù)

源碼過程

CachingExecutor # query
 |- MappedStatement # getBoundSql
  |- DynamicSqlSource # getBoundSql
   |- SqlNode # apply // 動(dòng)態(tài)SQL的組裝,以及將${}進(jìn)行字符串拼接
   |- SqlSourceBuilder # parse //這里是將#{}替換成 ?
   //組裝完成后封裝成StaticSqlSource
   //并調(diào)用StaticSqlSource的getBoundSql
   //new 一個(gè)新的BoundSql,傳入組裝好的SQL語句,以及查詢參數(shù)

執(zhí)行查詢過程

  • 從Configuration中根據(jù)id,取出一個(gè)MappedStatement
  • 將MappedStatement交由Executor處理
  • Executor中調(diào)用MappedStatement的getBoundSql,獲取組裝好的SQL語句,以及查詢參數(shù)
  • 根據(jù)查詢參數(shù),MappedStatement等信息,構(gòu)建出一個(gè)StatementHandler出來
  • StatementHandler新建一個(gè)Statement對(duì)象,并借助ParameterHandler完成對(duì)Statement的入?yún)⒔壎?/li>
  • 執(zhí)行查詢,并將結(jié)果集交由ResultSetHandler處理

源碼過程

DefaultSqlSession # selectList
 |- CachingExecutor # query
   |- BaseExecutor # query
     |- BaseExecutor # queryFromDatabase
       |- SimpleExecutor # doQuery
         |- Configuration # newStatementHandler
         |- SimpleExecutor # prepareStatement
         |- StatementHandler # query

緩存過程

  • 執(zhí)行查詢時(shí),首先是走CachingExecutor,CachingExecutor中檢查是否開啟二級(jí)緩存,若開啟,則會(huì)負(fù)責(zé)二級(jí)緩存數(shù)據(jù)的存取
  • 若沒開啟二級(jí)緩存,或二級(jí)緩存沒命中,進(jìn)入到BaseExecutor中,嘗試從一級(jí)緩存中拿數(shù)據(jù),若一級(jí)緩存中也沒有,則會(huì)訪問數(shù)據(jù)庫(kù)
  • 二級(jí)緩存是mapper級(jí)別的,即一個(gè)mapper,對(duì)應(yīng)一個(gè)二級(jí)緩存。在源碼中,二級(jí)緩存是被MappedStatement持有。二級(jí)緩存是通過mapper映射文件中的<cache/> 標(biāo)簽開啟的
  • 一級(jí)緩存無法關(guān)閉,但可以在全局配置中設(shè)置<setting name="localCacheScope" value="STATEMENT"/> 來使其失效(每次執(zhí)行操作都會(huì)清空一級(jí)緩存)

源碼過程

//二級(jí)緩存
CachingExecutor # query
 |- MappedStatement # getCache//獲取該mapper下的二級(jí)緩存
 |- TransactionalCacheManager # getObject //查找緩存中是否有數(shù)據(jù)
   |- TransactionalCache # getObject //查找緩存中是否有數(shù)據(jù)
 |-TransactionalCacheManager # putObject //存入二級(jí)緩存
   |- TransactionalCache # getObject
//若二級(jí)緩存未命中,走一級(jí)緩存
BaseExecutor # query
  |- PerpetualCache # getObject //從一級(jí)緩存中取數(shù)據(jù)

延遲加載過程

  • 在查詢結(jié)束后,調(diào)用ResultSetHandler對(duì)結(jié)果集進(jìn)行處理時(shí),若發(fā)現(xiàn)開啟了延遲加載,且有嵌套查詢,則會(huì)對(duì)結(jié)果生成一個(gè)代理對(duì)象
  • 當(dāng)調(diào)用結(jié)果的get方法,訪問延遲加載的數(shù)據(jù)時(shí),發(fā)現(xiàn)數(shù)據(jù)為空,則獲取其MappedStatement,執(zhí)行一次查詢,把查詢結(jié)果set到主對(duì)象中

源碼過程

DefaultResultSetHandler # createResultObject
 |- Configuration # getProxyFactory
 |- JavassistProxyFactory # createProxy
 // 默認(rèn)是使用JavassistProxyFactory

獲取Mapper代理過程

  • 調(diào)用Configuration中的mapperRegistry來查找這個(gè)mapper的類信息,會(huì)找到一個(gè)MapperProxyFactory對(duì)象
  • 使用JDK內(nèi)置的動(dòng)態(tài)代理,調(diào)用java.lang.reflect下的Proxy來生成一個(gè)代理類

源碼過程

DefaultSqlSession # getMapper
 |- MapperRegistry # getMapper
  |- MapperProxyFactory # newInstance
    |- MapperProxy # 構(gòu)造函數(shù)
    |- Proxy.newProxyInstance

mybatis插件過程

mybatis的插件會(huì)對(duì)以下幾個(gè)類起作用

  • Executor
  • StatementHandler
  • ParameterHandler
  • ResultSetHandler

實(shí)現(xiàn)Interceptor接口,覆寫intercept方法,在intercept方法中完成插件的攔截邏輯。

并覆寫plugin方法,在plugin方法中調(diào)用Plugin.wrap來生成一個(gè)代理對(duì)象并返回,即可。

底層也是使用的JDK動(dòng)態(tài)代理

源碼流程

//以Executor為例
DefaultSqlSessionFactory # openSession
  |- Configuration # newExecutor
    |- InterceptorChain # pluginAll

類關(guān)系總結(jié)

配置文件解析相關(guān)

  • BaseBuilder
  • XMLConfigBuilder
  • XMLMapperBuilder
  • 持有一個(gè)MapperBuilderAssistant
  • XMLStatementBuilder
  • XMLScriptBuilder

SQL組裝相關(guān)

  • SqlSource
    • DynamicSqlSource :
      • 含有動(dòng)態(tài)SQL,或 ${} ,會(huì)被解析封裝成這個(gè)類
    • RawSqlSource :
      • 不含動(dòng)態(tài)SQL,以及${} ,會(huì)被解析封裝成這個(gè)類
    • StaticSqlSource
      • Executor執(zhí)行查詢,調(diào)用getBoundSql方法時(shí),組裝好SQL語句,與查詢參數(shù)一同封裝起來,為這個(gè)類
  • SqlNode
    • TextSqlNode 文本節(jié)點(diǎn)
    • StaticTextSqlNode 文本節(jié)點(diǎn),且文本不包含 ${}
    • IfSqlNode
    • ForEachSqlNode
    • ChooseSqlNode
    • TrimSqlNode
    • 有2個(gè)子類,分別是
      • WhereSqlNode
      • SetSqlNode
    • MixedSqlNode作為根節(jié)點(diǎn),其有一個(gè) List<SqlNode> 字段

執(zhí)行相關(guān)

  • Executor

    • BaseExecutor

      其有3個(gè)子類,分別是

      • SimpleExecutor
      • ReuseExecutor
      • BatchExecutor
    • CachingExecutor

  • StatementHandler
    • RoutingStatementHandler

      僅作路由選擇功能

    • BaseStatementHandler

      其有3個(gè)子類,分別是

      • SimpleStatementHandler
      • PreparedStatementHandler
      • CallableStatementHandler
  • ParameterHandler

  • ResultSetHandler

  • Cache

    • PerpetualCache
    • LruCache
    • FifoCache
    • SerializedCache
    • LoggingCache
    • SynchronizedCache
    • SoftCache
    • WeakCache
    • TransactionalCache

到此這篇關(guān)于Mybatis的核心架構(gòu)及源碼解讀的文章就介紹到這了,更多相關(guān)Mybatis的核心架構(gòu)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java讀取Oracle大字段數(shù)據(jù)(CLOB)的2種方法

    Java讀取Oracle大字段數(shù)據(jù)(CLOB)的2種方法

    這篇文章主要介紹了Java讀取Oracle大字段數(shù)據(jù)(CLOB)的2種方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • java小知識(shí)之查詢數(shù)據(jù)庫(kù)數(shù)據(jù)的元信息

    java小知識(shí)之查詢數(shù)據(jù)庫(kù)數(shù)據(jù)的元信息

    這篇文章主要給大家介紹了關(guān)于java小知識(shí)之查詢數(shù)據(jù)庫(kù)數(shù)據(jù)的元信息,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2021-10-10
  • java實(shí)現(xiàn)登錄驗(yàn)證碼功能

    java實(shí)現(xiàn)登錄驗(yàn)證碼功能

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)登錄驗(yàn)證碼功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-10-10
  • spring boot使用sonarqube來檢查技術(shù)債務(wù)

    spring boot使用sonarqube來檢查技術(shù)債務(wù)

    今天小編就為大家分享一篇關(guān)于spring boot使用sonarqube來檢查技術(shù)債務(wù),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • 數(shù)據(jù)同步利器DataX簡(jiǎn)介及如何使用

    數(shù)據(jù)同步利器DataX簡(jiǎn)介及如何使用

    DataX?是阿里云?DataWorks數(shù)據(jù)集成?的開源版本,使用Java?語言編寫,在阿里巴巴集團(tuán)內(nèi)被廣泛使用的離線數(shù)據(jù)同步工具/平臺(tái),今天給大家分享一個(gè)阿里開源的數(shù)據(jù)同步工具DataX,在Github擁有14.8k的star,非常受歡迎
    2024-02-02
  • ssh框架實(shí)現(xiàn)文件上傳下載實(shí)例代碼

    ssh框架實(shí)現(xiàn)文件上傳下載實(shí)例代碼

    本篇文章主要介紹了ssh框架文件上傳下載實(shí)例代碼,實(shí)例分析了Spring+struts+Hibernate的使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。
    2017-03-03
  • JAVA Future類的使用詳解

    JAVA Future類的使用詳解

    這篇文章主要介紹了JAVA Future類的使用詳解,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下
    2021-04-04
  • springboot中實(shí)現(xiàn)上傳文件的功能簡(jiǎn)單示例

    springboot中實(shí)現(xiàn)上傳文件的功能簡(jiǎn)單示例

    這篇文章主要給大家介紹了關(guān)于springboot中實(shí)現(xiàn)上傳文件功能的相關(guān)資料,在Spring Boot中實(shí)現(xiàn)文件上傳下載功能相對(duì)簡(jiǎn)單,文中給出了代碼示例,需要的朋友可以參考下
    2023-09-09
  • 解決idea 拉取代碼出現(xiàn)的 “ Сannot Run Git Cannot identify version of git executable: no response“的問題

    解決idea 拉取代碼出現(xiàn)的 “ Сannot Run Git Cannot identify version of

    這篇文章主要介紹了解決idea 拉取代碼出現(xiàn)的 “ Сannot Run Git Cannot identify version of git executable: no response“的問題,需要的朋友可以參考下
    2020-08-08
  • Java使用ArrayList實(shí)現(xiàn)撲克牌的示例代碼

    Java使用ArrayList實(shí)現(xiàn)撲克牌的示例代碼

    學(xué)習(xí)了關(guān)于集合類的知識(shí),我們可以做一個(gè)小項(xiàng)目來加深對(duì)集合類知識(shí)的學(xué)習(xí)!本文就來利用ArrayList實(shí)現(xiàn)撲克牌發(fā)牌洗牌效果,需要的可以參考一下
    2022-10-10

最新評(píng)論