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

下載本文檔

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

文檔簡(jiǎn)介

1、iBATIS 框架主要的類層次結(jié)構(gòu)總體來(lái)說(shuō) iBATIS 的系統(tǒng)結(jié)構(gòu)還是比較簡(jiǎn)單的,它主要完成兩件事情:1. 根據(jù) JDBC 規(guī)范建立與數(shù)據(jù)庫(kù)的連接; 2. 通過(guò)反射打通 Java 對(duì)象與數(shù)據(jù)庫(kù)參數(shù)交互之間相互轉(zhuǎn)化關(guān)系。 iBATIS 的框架結(jié)構(gòu)也是按照這種思想來(lái)組織類層次結(jié)構(gòu)的,其實(shí)它是一種典型的交互式框架。先期準(zhǔn)備好交互的必要條件,然后構(gòu)建一個(gè)交互的環(huán)境,交互環(huán)境中還劃分成會(huì)話,每次的會(huì)話也有一個(gè)環(huán)境。當(dāng)這些環(huán)境都準(zhǔn)備好了以后,剩下的就是交換數(shù)據(jù)了。其實(shí)涉及到網(wǎng)絡(luò)通信,一般都會(huì)是類似的處理方式。圖 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é)束時(shí)必須要調(diào)用關(guān)閉接口關(guān)閉。當(dāng)使用者持有了 SqlMapClientImpl 對(duì)象就可以使用 iBATIS 來(lái)工作了。這里還要提到另外一個(gè)類 SqlMapExecutorDelegate 這個(gè)類從名字就可以看出他是執(zhí)行代理類。這個(gè)類非常重要,重要是因?yàn)樗詈狭擞脩舳说膱?zhí)行操作行為和執(zhí)行的環(huán)境,他持有執(zhí)行操作的所需要的數(shù)據(jù),同時(shí)提供管

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

4、rMap、ResultMap 兩個(gè)對(duì)象用于處理參數(shù)和經(jīng)過(guò)解析后交給數(shù)據(jù)庫(kù)處理的 Sql 對(duì)象。這樣除去數(shù)據(jù)庫(kù)的連接,一條 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)系,但是還有一個(gè)關(guān)鍵的部分就是,如何定義 SQL 語(yǔ)句中的參數(shù)與 Java 對(duì)象之間的關(guān)系,這其中還涉及到 Java 類型到數(shù)據(jù)庫(kù)類型的轉(zhuǎn)換等一系列問(wèn)題。數(shù)據(jù)的映射大體的過(guò)程是這樣的:根據(jù) Statement 中定義的 SQL 語(yǔ)句,解析出其中的參數(shù),按照其出現(xiàn)的順序保存在 Map 集合中,并按照 Sta

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

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

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

8、ntext 配置文件:清單 1. applicationContext.xml 下面是 Account.xml 的一個(gè) Statement:清單 2. Account.xml 中一個(gè) 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 的測(cè)試類:清單 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(); 回頁(yè)首iBATIS 對(duì) SQL 語(yǔ)句的解析這里所說(shuō)的 SQL 解析只是針對(duì) iBATIS 配置文件中所定義的 SQL 語(yǔ)句,如前一節(jié)中清單 2 中所示的查詢語(yǔ)句。和標(biāo)準(zhǔn)的 SQL 語(yǔ)句不同的是,參數(shù)的賦值是“#“包裹的變量名。如何解析這個(gè)變量就是 iBATIS 要完成的工作。當(dāng)然 SQL 的表達(dá)形式還有很多其他的形式如動(dòng)態(tài) SQL 等?,F(xiàn)在我們關(guān)心的是當(dāng)我們執(zhí)行:清單 4. 執(zhí)行查詢方法accountDAO.selectAccountById(account) iBATIS 將會(huì)選擇清單

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

14、XXX(i, parameter) 提交參數(shù)。在清單 3 中,我們給 account 對(duì)象的 id 屬性和 firstName 屬性分別賦值為 1 和“tao“,當(dāng)執(zhí)行清單 4 中的這段代碼時(shí),iBATIS 必須把這兩個(gè)屬性值傳給清單 2 中 SQL 語(yǔ)句中對(duì)象的參數(shù)。這個(gè)是怎么做到的,其實(shí)很簡(jiǎn)單,在圖 3 中描述了與 ParameterMap 相關(guān)的類的關(guān)系,這些類中都保存了在 SqlMap 配置文件初始化是解析清單 2 中 Statement 的所有必要的信息,具體的信息是這樣的:最終的 SQL 語(yǔ)句是:清單 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 對(duì)象的 id 屬性。#firstName# 同樣被解析成 Account 對(duì)象的 firstName 屬性,而 parameterClass=Account指明了 Account 的類類型。注意到清單 5 中 #id:INTEGER# 和 #f

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

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

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

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

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

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論