框架主要的類層次結(jié)構(gòu)_第1頁
框架主要的類層次結(jié)構(gòu)_第2頁
框架主要的類層次結(jié)構(gòu)_第3頁
框架主要的類層次結(jié)構(gòu)_第4頁
框架主要的類層次結(jié)構(gòu)_第5頁
已閱讀5頁,還剩7頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、iBATIS 框架主要的類層次結(jié)構(gòu)總體來說 iBATIS 的系統(tǒng)結(jié)構(gòu)還是比較簡單的,它主要完成兩件事情:1. 根據(jù) JDBC 規(guī)范建立與數(shù)據(jù)庫的連接; 2. 通過反射打通 Java 對象與數(shù)據(jù)庫參數(shù)交互之間相互轉(zhuǎn)化關(guān)系。 iBATIS 的框架結(jié)構(gòu)也是按照這種思想來組織類層次結(jié)構(gòu)的,其實它是一種典型的交互式框架。先期準備好交互的必要條件,然后構(gòu)建一個交互的環(huán)境,交互環(huán)境中還劃分成會話,每次的會話也有一個環(huán)境。當(dāng)這些環(huán)境都準備好了以后,剩下的就是交換數(shù)據(jù)了。其實涉及到網(wǎng)絡(luò)通信,一般都會是類似的處理方式。圖 1 是 iBATIS 框架的主要的類層次結(jié)構(gòu)圖:圖 1. iBATIS 框架的主要的類層次結(jié)

2、構(gòu)圖上面的類圖中左邊 SqlMapClient 接口主要定義了客戶端的操作行為包括 select、insert、update、delete。而右邊主要是定義了當(dāng)前客戶端在當(dāng)前線程的執(zhí)行環(huán)境。SqlMapSession 可以共享使用,也可以自己創(chuàng)建,如果是自己創(chuàng)建在結(jié)束時必須要調(diào)用關(guān)閉接口關(guān)閉。當(dāng)使用者持有了 SqlMapClientImpl 對象就可以使用 iBATIS 來工作了。這里還要提到另外一個類 SqlMapExecutorDelegate 這個類從名字就可以看出他是執(zhí)行代理類。這個類非常重要,重要是因為他耦合了用戶端的執(zhí)行操作行為和執(zhí)行的環(huán)境,他持有執(zhí)行操作的所需要的數(shù)據(jù),同時提供管

3、理著執(zhí)行操作依賴的環(huán)境。所以他是一個強耦合的類,也可以看做是個工具類?;仨撌譱BATIS 框架的設(shè)計策略iBATIS 主要的設(shè)計目的還是為了讓我們執(zhí)行 SQL 時對輸入輸出的數(shù)據(jù)管理更加方便,所以如何方便的讓我們寫出 SQL 和方便的獲取 SQL 的執(zhí)行結(jié)果才是 iBATIS 的核心競爭力。那么 iBATIS 是怎么實現(xiàn)它的核心競爭力的呢?iBATIS 框架的一個重要組成部分就是其 SqlMap 配置文件,SqlMap 配置文件的核心是 Statement 語句包括 CIUD。 iBATIS 通過解析 SqlMap 配置文件得到所有的 Statement 執(zhí)行語句,同時會形成 Paramete

4、rMap、ResultMap 兩個對象用于處理參數(shù)和經(jīng)過解析后交給數(shù)據(jù)庫處理的 Sql 對象。這樣除去數(shù)據(jù)庫的連接,一條 SQL 的執(zhí)行條件已經(jīng)具備了。圖 2 描述了 Statement 有關(guān)的類結(jié)構(gòu)圖:圖 2. Statement 有關(guān)的類結(jié)構(gòu)圖圖 2 給出了圍繞 SQL 執(zhí)行的基本的結(jié)構(gòu)關(guān)系,但是還有一個關(guān)鍵的部分就是,如何定義 SQL 語句中的參數(shù)與 Java 對象之間的關(guān)系,這其中還涉及到 Java 類型到數(shù)據(jù)庫類型的轉(zhuǎn)換等一系列問題。數(shù)據(jù)的映射大體的過程是這樣的:根據(jù) Statement 中定義的 SQL 語句,解析出其中的參數(shù),按照其出現(xiàn)的順序保存在 Map 集合中,并按照 Sta

5、tement 中定義的 ParameterMap 對象類型解析出參數(shù)的 Java 數(shù)據(jù)類型。并根據(jù)其數(shù)據(jù)類型構(gòu)建 TypeHandler 對象,參數(shù)值的復(fù)制是通過 DataExchange 對象完成的。圖 3 是參數(shù)映射相關(guān)的類結(jié)構(gòu)圖:圖 3. 參數(shù)映射相關(guān)的類結(jié)構(gòu)圖圖 3 是輸入?yún)?shù)的映射結(jié)構(gòu)情況,返回結(jié)果 ResultMap 的映射情況也是類似的。主要就是要解決 SQL 語句中的參數(shù)與返回結(jié)果的列名與 Statement 中定義的 parameterClass 和 resultClass 中屬性的對應(yīng)關(guān)系?;仨撌譱BATIS 框架的運行原理前面大體分析了 iBATIS 框架的主要類的結(jié)構(gòu),

6、這里主要看一下這些類是如何串聯(lián)起來、如何工作的。圖 4 描述了整個過程的主要執(zhí)行步驟。圖 4.iBATIS 運行的主要執(zhí)行步驟上圖中描述的 SqlMapSession 對象的創(chuàng)建和釋放根據(jù)不同情況會有不同,因為 SqlMapSession 負責(zé)創(chuàng)建數(shù)據(jù)庫的連接,包括對事務(wù)的管理,iBATIS 對管理事務(wù)既可以自己管理也可以由外部管理,iBATIS 自己管理是通過共享 SqlMapSession 對象實現(xiàn)的,多個 Statement 的執(zhí)行時共享一個 SqlMapSession 實例,而且都是線程安全的。如果是外部程序管理就要自己控制 SqlMapSession 對象的生命周期。圖 5 是通過

7、Spring 調(diào)用 iBATIS 執(zhí)行一個 Statement 的一個詳細的時序圖:圖 5. Spring 調(diào)用 iBATIS 執(zhí)行一個 Statement 的時序圖(查看圖 5 的 清晰版本。)iBATIS 的主要工作連接、交互,所以必須根據(jù)不同的交易成本設(shè)計不同的交易環(huán)境?;仨撌资纠旅嫖覀儗⒏鶕?jù)一個具體的實例解析一個 Statement 如何完成映射的,我們用一個典型的查詢語句看看 Java 對象中的數(shù)據(jù)時如何賦給 SQL 中的參數(shù)的,再看看 SQL 的查詢結(jié)果是如何轉(zhuǎn)成 Java 對象的。先看一下示例的部分代碼和配置文件,完整的代碼請看附件。Spring 的 applicationCo

8、ntext 配置文件:清單 1. applicationContext.xml 下面是 Account.xml 的一個 Statement:清單 2. Account.xml 中一個 Statement select ACC_ID, ACC_FIRST_NAME as firstName, ACC_LAST_NAME as lastName, ACC_EMAIL as emailAddress, ACC_DATE from ACCOUNT where ACC_ID = #id:INTEGER# and ACC_FIRST_NAME = #firstName#下面是 Java 的測試類:清單 3

9、. SimpleTestpublic class SimpleTest public static void main(String args) ApplicationContext factory = new ClassPathXmlApplicationContext(/com/mydomain/data/applicationContext.xml); final AccountDAO accountDAO = (AccountDAO) factory.getBean(accountDAO); final Account account = new Account(); account.

10、setId(1); account.setFirstName(tao); account.setLastName(bao); account.setEmailAddress(junshan); account.setDate(new Date(); try accountDAO.getSqlMapTransactionTemplate().execute(new TransactionCallback() public Object doInTransaction(TransactionStatus status) try accountDAO.deleteAccount(account.ge

11、tId(); accountDAO.insertAccount(account); /account.setLastName(bobo); /accountDAO.updateAccount(account); Account result = accountDAO.selectAccount(account); System.out.println(result); return null; catch (Exception e) status.setRollbackOnly(); return false; ); /accountDAO.getSqlMapClient().commitTr

12、ansaction(); catch (Exception e) e.printStackTrace(); 回頁首iBATIS 對 SQL 語句的解析這里所說的 SQL 解析只是針對 iBATIS 配置文件中所定義的 SQL 語句,如前一節(jié)中清單 2 中所示的查詢語句。和標準的 SQL 語句不同的是,參數(shù)的賦值是“#“包裹的變量名。如何解析這個變量就是 iBATIS 要完成的工作。當(dāng)然 SQL 的表達形式還有很多其他的形式如動態(tài) SQL 等。現(xiàn)在我們關(guān)心的是當(dāng)我們執(zhí)行:清單 4. 執(zhí)行查詢方法accountDAO.selectAccountById(account) iBATIS 將會選擇清單

13、 2 這條 Statement 來解析,最終會把它解析成一個標準的 SQL 提交給數(shù)據(jù)庫執(zhí)行,并且會設(shè)置兩個選擇條件參數(shù)。這個過程中參數(shù)映射的細節(jié)是什么樣子呢?在前面的第二小節(jié)中已經(jīng)說明了,iBATIS 會把 SqlMap 配置文件解析成一個個 Statement,其中包括 ParameterMap、ResultMap,以及解析后的 SQL。當(dāng) iBATIS 構(gòu)建好 RequestScope 執(zhí)行環(huán)境后,要做的工作就是把傳過來的對象數(shù)據(jù)結(jié)合 ParameterMap 中信息提取出一個參數(shù)數(shù)組,這個數(shù)組的順序就是對應(yīng)于 SQL 中參數(shù)的順序,然后會調(diào)用 preparedStatement.set

14、XXX(i, parameter) 提交參數(shù)。在清單 3 中,我們給 account 對象的 id 屬性和 firstName 屬性分別賦值為 1 和“tao“,當(dāng)執(zhí)行清單 4 中的這段代碼時,iBATIS 必須把這兩個屬性值傳給清單 2 中 SQL 語句中對象的參數(shù)。這個是怎么做到的,其實很簡單,在圖 3 中描述了與 ParameterMap 相關(guān)的類的關(guān)系,這些類中都保存了在 SqlMap 配置文件初始化是解析清單 2 中 Statement 的所有必要的信息,具體的信息是這樣的:最終的 SQL 語句是:清單 5. 解析后的 SQLselect ACC_ID, ACC_FIRST_NAME

15、 as firstName, ACC_LAST_NAME as lastName, ACC_EMAIL as emailAddress, ACC_DATEfrom ACCOUNTwhere ACC_ID = ? and ACC_FIRST_NAME = ? #id:INTEGER# 將被解析成 JDBC 類型是 INTEGER,參數(shù)值取 Account 對象的 id 屬性。#firstName# 同樣被解析成 Account 對象的 firstName 屬性,而 parameterClass=Account指明了 Account 的類類型。注意到清單 5 中 #id:INTEGER# 和 #f

16、irstName# 都被替換成“?”,iBATIS 如何保證它們的順序?在解析清單 2 過程中,iBATIS 會根據(jù)“#”分隔符取出合法的變量名構(gòu)建參數(shù)對象數(shù)組,數(shù)組的順序就是 SQL 中變量出現(xiàn)的順序。接著 iBATIS 會根據(jù)這些變量和 parameterClass 指定的類型創(chuàng)建合適的 dataExchange 和 parameterPlan 對象。parameterPlan 對象中按照前面的順序保存了變量的 setter 和 getter 方法列表。所以 parameter 的賦值就是根據(jù) parameterPlan 中保存的 getter 方法列表以及傳進來的 account 對象利

17、用反射機制得到清單 5 對應(yīng)的參數(shù)值數(shù)組,再將這個數(shù)組按照指定的 JDBC 類型提交給數(shù)據(jù)庫。以上這些過程可以用圖 6 的時序圖清楚的描述:圖 6. 映射參數(shù)值到數(shù)據(jù)庫過程時序圖上圖 4 中在 8 步驟中如果 value 值為空時會設(shè)置 preparedStatement.setNull(i , jdbcType) 如果在清單 2 中的變量沒有設(shè)置 jdbcType 類型時有可能會出錯?;仨撌讛?shù)據(jù)庫字段映射到 Java 對象數(shù)據(jù)庫執(zhí)行完 SQL 后會返回執(zhí)行結(jié)果,在第 4 小節(jié)的例子中滿足 id 為 1、firstName 為“tao”的信息有兩條,iBATIS 如何將這兩條記錄設(shè)置到 acc

18、ount 對象中呢?和 ParameterMap 類似,填充返回信息需要的資源都已經(jīng)包含在 ResultMap 中。當(dāng)有了保存返回結(jié)果的 ResultSet 對象后,就是要把列名映射到 account 對象的對應(yīng)屬性中。這個過程大體如下:根據(jù) ResultMap 中定義的 ResultClass 創(chuàng)建返回對象,這里就是 account 對象。獲取這個對象的所有可寫的也就是 setter 方法的屬性數(shù)組,接著根據(jù)返回 ResultSet 中的列名去匹配前面的屬性數(shù)組,把匹配結(jié)果構(gòu)造成一個集合(resultMappingList),后面是選擇 DataExchange 類型、AccessPlan

19、類型為后面的真正的數(shù)據(jù)交換提供支持。根據(jù) resultMappingList 集合從 ResultSet 中取出列對應(yīng)的值,構(gòu)成值數(shù)組(columnValues),這個數(shù)組的順序就是 SQL 中對應(yīng)列名的順序。最后把 columnValues 值調(diào)用 account 對象的屬性的 setter 方法設(shè)置到對象中。這個過程可以用下面的時序圖來表示:圖 7. 映射返回對象時序圖回頁首示例運行的結(jié)果前兩個小節(jié)主要描述了輸入?yún)?shù)和輸出結(jié)果的映射原理,這里再結(jié)合第 4 小節(jié)的示例分析一下執(zhí)行清單 3 代碼的結(jié)果。執(zhí)行清單 3 所示代碼打印的結(jié)果為:清單 6. 示例程序的運行結(jié)果Accountid=0,

20、firstName=tao, lastName=bobo, emailAddress=junshan上面的結(jié)果和我們預(yù)想的結(jié)果似乎有所不同,看代碼我們插入數(shù)據(jù)庫的 account 對象各屬性值分別為 1,“tao”,“bao”,“junshan”,“時間”,后面調(diào)用清單 2 的查詢,返回應(yīng)該是一樣的結(jié)果才對。id 的結(jié)果不對、date 屬性值丟失。再仔細看看清單 2 這個 Statement 可以發(fā)現(xiàn),返回結(jié)果的列名分別是 ACC_ID,firstName,lastName,emailAddress,ACC_DATE 其中 id 和 date 并不能映射到 Account 類的屬性中。id 被賦了默認數(shù)字 0,而 date 沒有被賦值。還有一個值得注意的地方是變量 id 后面跟上 JDBC 類型,這個 JDBC 類型有沒有用?通常情況下都沒有用,因此你可以不設(shè),iBATIS 會自動選擇默認的類型。但是如果你要這個這個值可能為空時如果沒有指定 JDBC 類型可能就有問題了,在 Oracle 中雖然能正常工作但是會引起 Oracle 這當(dāng)前這個 SQL 有多次編譯現(xiàn)象,因此會影響數(shù)據(jù)庫的性能。還有當(dāng)同一個 Java 類型如果對應(yīng)多個 JDBC 類型(如 Date 對應(yīng) JDBC 類型有 java.sql.Da

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論