摘要:最近查找一個(gè)生產(chǎn)問(wèn)題的原因,需要深入研究框架的源碼。將會(huì)保存解析字段相關(guān)信息。會(huì)按照數(shù)組中的順序使用反射獲取方法返回值生成數(shù)組。第四步,使用獲取返回值,在這一步將會(huì)完成數(shù)據(jù)庫(kù)類(lèi)型與類(lèi)型的轉(zhuǎn)化。
最近查找一個(gè)生產(chǎn)問(wèn)題的原因,需要深入研究 ibatis 框架的源碼。雖然最后證明問(wèn)題的原因與 ibatis 無(wú)關(guān),但是這個(gè)過(guò)程加深了對(duì) ibatis 框架原理的理解。
這篇文章主要就來(lái)講講 ibatis 框架的原理。
可能現(xiàn)在很多人已不再使用 ibatis 或者說(shuō)也沒(méi)聽(tīng) ibatis,不過(guò)肯定了解過(guò) Mybatis。ibatis 就是 Mybatis框架的前身,雖然 ibatis 框架已經(jīng)比較老,但是其核心功能與 Mybatis 一致。ibatis 解決的痛點(diǎn)
我們先看一個(gè)使用 JDBC 查詢的例子。
使用原生 JDBC 查詢,存在兩個(gè)痛點(diǎn):
使用非常繁瑣,且需要處理各種數(shù)據(jù)庫(kù)異常,并且還需要關(guān)閉各種資源。
數(shù)據(jù)轉(zhuǎn)化麻煩。查詢之前需要從 Java 對(duì)象屬性值設(shè)置到 PreparedStatement中,查詢返回之后又需要從 ResultSet獲取返回設(shè)置到返回對(duì)象中。
在 ibatis 中封裝這些繁雜數(shù)據(jù)庫(kù)連接查詢代碼,并處理了各類(lèi)異常以及關(guān)閉各種資源。另外 ibatis 自動(dòng)處理 Java 對(duì)象與數(shù)據(jù)庫(kù)類(lèi)型之間的自動(dòng)轉(zhuǎn)化,讓業(yè)務(wù)代碼與 SQL 代碼之間做到了解耦。
數(shù)據(jù)類(lèi)型轉(zhuǎn)化原理數(shù)據(jù)類(lèi)型轉(zhuǎn)化主要分為兩類(lèi),一,傳入查詢的 Java 對(duì)象數(shù)據(jù)轉(zhuǎn)化成 SQL 類(lèi)型數(shù)據(jù)。二 查詢返回的數(shù)據(jù)庫(kù)信息映射到 Java 對(duì)象中。
ibatis SQL 需要定義在配置文件中,一個(gè)查詢 SQL 語(yǔ)句配置如下:
ibatis 框架啟動(dòng)過(guò)程將會(huì)解析配置文件,生成 MappedStatement 的子類(lèi)。如 select 配置會(huì)生成對(duì)應(yīng)的 SelectStatement 對(duì)象。
MappedStatement 相關(guān)類(lèi)圖如下。
在 MappedStatement 中將會(huì)保存存在兩個(gè)重要的對(duì)象,ParameterMap與 ResultMap,通過(guò)這兩個(gè)對(duì)象將會(huì)完成 Java 類(lèi)型與數(shù)據(jù)庫(kù)類(lèi)型的相互轉(zhuǎn)化。
Java 對(duì)象轉(zhuǎn)化成數(shù)據(jù)庫(kù)類(lèi)型以上面 select 配置為例,我們這里需要做的是從傳入的 com.query.QueryDO對(duì)象中獲取屬性值,然后通過(guò) PreparedStatement.setxx 設(shè)置到查詢參數(shù)中。
ibatis 解析配置中 SQL 語(yǔ)句時(shí),將會(huì)獲取 # 之間的內(nèi)容,將其替換成 ?。然后按照順序保存到一個(gè) ParameterMapping[] 數(shù)組中,這個(gè)數(shù)組將會(huì)保存到 ParameterMap 對(duì)象中。
ParameterMapping 將會(huì)保存解析字段相關(guān)信息。
最終解析后的 SQL 為:
select * from TEST_QUERY where ID=?
該 SQL 就可以通過(guò) connection.prepareStatement("select * from TEST_QUERY where ID=?"); 生成 PreparedStatement 對(duì)象。
接著 ibatis 會(huì)根據(jù) ParameterMapping 和 parameterClass 指定的類(lèi)型創(chuàng)建合適的 dataExchange 和 parameterPlan 對(duì)象。
其中 parameterPlan 對(duì)象會(huì)按照 ParameterMapping 數(shù)組中順序保存了變量的 setter 和 getter 方法數(shù)組。
dataExchange 會(huì)按照 ParameterMapping 數(shù)組中的順序使用反射獲取 parameterPlan getter 方法返回值生成 parameters 數(shù)組。
最后循環(huán) ParameterMapping 數(shù)組,在 TypeHandler 調(diào)用 PreparedStatement.setxx 設(shè)置相關(guān)值。
TypeHandler 存在很多子類(lèi),通過(guò)這些子類(lèi)正確處理了 Java 對(duì)象與數(shù)據(jù)庫(kù)類(lèi)型轉(zhuǎn)化。
轉(zhuǎn)化的時(shí)序圖為:
時(shí)序圖來(lái)源于:https://www.ibm.com/developer...數(shù)據(jù)庫(kù)字段映射到 Java 對(duì)象
SQL 執(zhí)行結(jié)束之后將會(huì)返回查詢結(jié)果,這里將會(huì)使 SQL 查詢結(jié)果轉(zhuǎn)化為返回結(jié)果 com.query.QueryDO。這里需要用到上面提到 ResultMap 對(duì)象。
當(dāng) SQL 執(zhí)行結(jié)束返回 ResultSet 對(duì)象之后,使用 ResultSet.getMetaData() 獲取返回信息元數(shù)據(jù)對(duì)象 ResultSetMetaData 。
從 ResultSetMetaData 可以獲取返回結(jié)果字段名,類(lèi)型等信息,然后按照順序存入 ResultMapping 數(shù)組中。
然后按照 ResultMapping 數(shù)組中使用 TypeHandler調(diào)用 ResultSet.getxx 獲取實(shí)際返回?cái)?shù)據(jù),保存到 columnValues 數(shù)組中。
在 ResultMap 對(duì)象會(huì)根據(jù) ResultMapping 與 resultClass指定的類(lèi)型合適的 dataExchange 和 resultPlan對(duì)象。resultPlan對(duì)象與上面的 parameterPlan 對(duì)象一樣也會(huì)保存著變量的 setter 和 getter 方法數(shù)組。
最后先根據(jù) resultClass 反射生成返回對(duì)象,然后使用反射調(diào)用 resultPlan setter 方法,依次設(shè)置相關(guān)值。
映射返回對(duì)象時(shí)序圖為:
時(shí)序圖來(lái)源于:https://www.ibm.com/developer...ibatis 樣板代碼
上面講完了 ibatis 數(shù)據(jù)類(lèi)型的轉(zhuǎn)化原理,接著我們來(lái)看下 ibatis 調(diào)用 JDBC 樣板代碼。
使用 ibatis 執(zhí)行查詢語(yǔ)句時(shí),如 queryForObject,調(diào)用到 SqlMapExecutorDelegate 。在 SqlMapExecutorDelegate 中將會(huì)會(huì)做一些前提準(zhǔn)備,比如準(zhǔn)備事務(wù),最后會(huì)將 SQL 語(yǔ)句委托給 SqlExecutor 執(zhí)行。
這里使用委托者模式,接受請(qǐng)求的對(duì)象將請(qǐng)求委托給另一個(gè)對(duì)象來(lái)處理。這種模式的優(yōu)點(diǎn)在于解耦了業(yè)務(wù)代碼與實(shí)際執(zhí)行代碼的聯(lián)系,在于對(duì)外隱藏真正執(zhí)行對(duì)象,易于擴(kuò)展。
在 SqlExecutor#executeQuery 執(zhí)行過(guò)程主要分為以下三步。
第一步,獲取 PreparedStatement,使用 conn.prepareStatement(sql) 獲取。
第二步調(diào)用 PreparedStatement.setxxx 方法設(shè)置參數(shù)。上文中的 Java 對(duì)象類(lèi)型轉(zhuǎn)化成 SQL 類(lèi)型在這里完成。
第三步,調(diào)用 PreparedStatement.execute() 執(zhí)行 SQL 語(yǔ)句。
第四步,使用 ResultSet 獲取返回值,在這一步將會(huì)完成 數(shù)據(jù)庫(kù)類(lèi)型與 Java 類(lèi)型的轉(zhuǎn)化。
幫助鏈接深入分析 iBATIS 框架之系統(tǒng)架構(gòu)與映射原理
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76010.html
摘要:基本綱要組成動(dòng)態(tài)配置配置核心源碼分析源碼解析源碼解析源碼解析源碼解析手寫(xiě)框架是什么本質(zhì)是一種半自動(dòng)的框架,前身是其源于和的組合,除了和映射關(guān)系之外,還需要編寫(xiě)語(yǔ)句映射三要素映射規(guī)則快速入門(mén)加入的依賴添加的配置文件場(chǎng)景介紹編寫(xiě)實(shí)體類(lèi)接口以及文 showImg(https://segmentfault.com/img/bVblrnC); Mybatis基本綱要 Mybatis組成 · 動(dòng)態(tài)...
摘要:攔截器的使用場(chǎng)景主要是更新數(shù)據(jù)庫(kù)的通用字段,分庫(kù)分表,加解密等的處理。攔截器均需要實(shí)現(xiàn)該接口。攔截器攔截器的使用需要查看每一個(gè)所提供的方法參數(shù)。對(duì)應(yīng)構(gòu)造器,為,為,為??蓞⒖紨r截器原理探究。 攔截器(Interceptor)在 Mybatis 中被當(dāng)做插件(plugin)對(duì)待,官方文檔提供了 Executor(攔截執(zhí)行器的方法),ParameterHandler(攔截參數(shù)的處理),Re...
摘要:一定義是一款優(yōu)秀的持久層框架,它支持定制化存儲(chǔ)過(guò)程以及高級(jí)映射。別名與類(lèi)中的屬性名保持一致。接口的名字建議為,與文件保持一致編寫(xiě)文件,名字與接口名保持一致。 一、定義 MyBatis 是一款優(yōu)秀的持久層框架,它支持定制化 SQL、存儲(chǔ)過(guò)程以及高級(jí)映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動(dòng)設(shè)置參數(shù)以及獲取結(jié)果集。MyBatis 可以使用簡(jiǎn)單的 XML 或注解來(lái)配置和映射...
摘要:跳槽時(shí)時(shí)刻刻都在發(fā)生,但是我建議大家跳槽之前,先想清楚為什么要跳槽。切不可跟風(fēng),看到同事一個(gè)個(gè)都走了,自己也盲目的開(kāi)始面試起來(lái)期間也沒(méi)有準(zhǔn)備充分,到底是因?yàn)榧夹g(shù)原因影響自己的發(fā)展,偏移自己規(guī)劃的軌跡,還是錢(qián)給少了,不受重視。 跳槽時(shí)時(shí)刻刻都在發(fā)生,但是我建議大家跳槽之前,先想清楚為什么要跳槽。切不可跟風(fēng),看到同事一個(gè)個(gè)都走了,自己也盲目的開(kāi)始面試起來(lái)(期間也沒(méi)有準(zhǔn)備充分),到底是因?yàn)榧?..
摘要:配置測(cè)試描述測(cè)試類(lèi)技術(shù)部查詢表至此初步配置完成執(zhí)行過(guò)程獲取解析成接收方法方法方法屬性定位方法數(shù)據(jù)綁定到具體方法提交傳輸獲取配置解析標(biāo)簽對(duì)象獲取過(guò)程源碼使用 MyBatis 配置 4.0.0 com.huifer mybatisBook 1.0-SNAPSHOT UTF-8 UTF-8 1...
閱讀 3556·2021-11-22 11:59
閱讀 954·2021-09-27 13:36
閱讀 3616·2021-09-24 09:47
閱讀 2266·2021-09-01 11:39
閱讀 985·2021-08-31 09:37
閱讀 2316·2021-08-05 10:01
閱讀 1677·2019-08-30 15:55
閱讀 703·2019-08-30 15:54