天天看點

ibatis工作原理

摘要: iBATIS 通過 SQL Map 将 Java 對象映射成 SQL 語句和将結果集再轉化成 Java 對象,與其他 ORM 架構相比,既解決了 Java 對象與輸入參數和結果集的映射,又能夠讓使用者友善的手寫使用 SQL 語句。本文主要介紹了 iBATIS 架構的體系結構和運作流程,以及 iBATIS 如何完成 SQL 語句的解析與 Java 對象與資料字段映射關系的建立,最後用一個執行個體說明了 iBATIS 是如何幫我們完成工作的。

iBATIS 架構主要的類層次結構

總體來說 iBATIS 的系統結構還是比較簡單的,它主要完成兩件事情:

  1. 根據 JDBC 規範建立與資料庫的連接配接;
  2. 通過反射打通 Java 對象與資料庫參數互動之間互相轉化關系。

iBATIS 的架構結構也是按照這種思想來組織類層次結構的,其實它是一種典型的互動式架構。先期準備好互動的必要條件,然後建構一個互動的環境,互動環境中還劃分成會話,每次的會話也有一個環境。當這些環境都準備好了以後,剩下的就是交換資料了。其實涉及到網絡通信,一般都會是類似的處理方式。

圖 1 是 iBATIS 架構的主要的類層次結構圖:

圖 1. iBATIS 架構的主要的類層次結構圖
ibatis工作原理

上面的類圖中左邊 SqlMapClient 接口主要定義了用戶端的操作行為包括 select、insert、update、delete。而右邊主要是定義了目前用戶端在目前線程的執行環境。SqlMapSession 可以共享使用,也可以自己建立,如果是自己建立在結束時必須要調用關閉接口關閉。

當使用者持有了 SqlMapClientImpl 對象就可以使用 iBATIS 來工作了。這裡還要提到另外一個類 SqlMapExecutorDelegate 這個類從名字就可以看出他是執行代理類。這個類非常重要,重要是因為他耦合了使用者端的執行操作行為和執行的環境,他持有執行操作的所需要的資料,同時提供管理着執行操作依賴的環境。是以他是一個強耦合的類,也可以看做是個工具類。

回頁首

iBATIS 架構的設計政策

iBATIS 主要的設計目的還是為了讓我們執行 SQL 時對輸入輸出的資料管理更加友善,是以如何友善的讓我們寫出 SQL 和友善的擷取 SQL 的執行結果才是 iBATIS 的核心競争力。那麼 iBATIS 是怎麼實作它的核心競争力的呢?

iBATIS 架構的一個重要組成部分就是其 SqlMap 配置檔案,SqlMap 配置檔案的核心是 Statement 語句包括 CIUD。 iBATIS 通過解析 SqlMap 配置檔案得到所有的 Statement 執行語句,同時會形成 ParameterMap、ResultMap 兩個對象用于處理參數和經過解析後交給資料庫處理的 Sql 對象。這樣除去資料庫的連接配接,一條 SQL 的執行條件已經具備了。

圖 2 描述了 Statement 有關的類結構圖:

圖 2. Statement 有關的類結構圖
ibatis工作原理

圖 2 給出了圍繞 SQL 執行的基本的結構關系,但是還有一個關鍵的部分就是,如何定義 SQL 語句中的參數與 Java 對象之間的關系,這其中還涉及到 Java 類型到資料庫類型的轉換等一系列問題。

資料的映射大體的過程是這樣的:根據 Statement 中定義的 SQL 語句,解析出其中的參數,按照其出現的順序儲存在 Map 集合中,并按照 Statement 中定義的 ParameterMap 對象類型解析出參數的 Java 資料類型。并根據其資料類型建構 TypeHandler 對象,參數值的複制是通過 DataExchange 對象完成的。

圖 3 是參數映射相關的類結構圖:

圖 3. 參數映射相關的類結構圖
ibatis工作原理

圖 3 是輸入參數的映射結構情況,傳回結果 ResultMap 的映射情況也是類似的。主要就是要解決 SQL 語句中的參數與傳回結果的列名與 Statement 中定義的 parameterClass 和 resultClass 中屬性的對應關系。

回頁首

iBATIS 架構的運作原理

前面大體分析了 iBATIS 架構的主要類的結構,這裡主要看一下這些類是如何串聯起來、如何工作的。圖 4 描述了整個過程的主要執行步驟。

圖 4.iBATIS 運作的主要執行步驟
ibatis工作原理

上圖中描述的 SqlMapSession 對象的建立和釋放根據不同情況會有不同,因為 SqlMapSession 負責建立資料庫的連接配接,包括對事務的管理,iBATIS 對管理事務既可以自己管理也可以由外部管理,iBATIS 自己管理是通過共享 SqlMapSession 對象實作的,多個 Statement 的執行時共享一個 SqlMapSession 執行個體,而且都是線程安全的。如果是外部程式管理就要自己控制 SqlMapSession 對象的生命周期。

圖 5 是通過 Spring 調用 iBATIS 執行一個 Statement 的一個詳細的時序圖:

圖 5. Spring 調用 iBATIS 執行一個 Statement 的時序圖
ibatis工作原理

(檢視圖 5 的 清晰版本。)

iBATIS 的主要工作連接配接、互動,是以必須根據不同的交易成本設計不同的交易環境。

回頁首

示例

下面我們将根據一個具體的執行個體解析一個 Statement 如何完成映射的,我們用一個典型的查詢語句看看 Java 對象中的資料時如何賦給 SQL 中的參數的,再看看 SQL 的查詢結果是如何轉成 Java 對象的。

先看一下示例的部分代碼和配置檔案,完整的代碼請看附件。

Spring 的 applicationContext 配置檔案:

清單 1. applicationContext.xml
<beans>
    <bean id="sqlMapTransactionManager" 
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="sqlMapTransactionTemplate" 
        class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="sqlMapTransactionManager"/>
    </bean>
    <!--sql map -->
    <bean id="sqlMapClient" 
        class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocation" value="com/mydomain/data/SqlMapConfig.xml"/>
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <bean id="dataSource" name="dataSource" 
        class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
        <