=====================================================
概述
JDBC類(lèi)庫(kù)使得Java程序可以訪問(wèn)多個(gè)數(shù)據(jù)源,但在大多數(shù)情況下,這個(gè)數(shù)據(jù)源是關(guān)系數(shù)據(jù)庫(kù),并且通過(guò)SQL訪問(wèn)。然而,實(shí)現(xiàn)JDBC技術(shù)的驅(qū)動(dòng)也可以基于其它的數(shù)據(jù)源,包括遺留文件系統(tǒng)和面向?qū)ο蟮南到y(tǒng)。JDBC類(lèi)庫(kù)的一個(gè)主要目的就是提供一個(gè)應(yīng)用程序訪問(wèn)多種數(shù)據(jù)源的標(biāo)準(zhǔn)接口。
這一章介紹JDBC類(lèi)庫(kù)的一些關(guān)鍵概念,并描述JDBC應(yīng)用的兩個(gè)通用環(huán)境及其中的功能實(shí)現(xiàn)。兩層和三層模型都是能被實(shí)現(xiàn)在多個(gè)物理配置上的邏輯模型。
=====================================================
4.1 創(chuàng)建連接
JDBC類(lèi)庫(kù)中的Connection接口代表了底層數(shù)據(jù)源的一個(gè)連接。
在典型場(chǎng)景中,JDBC應(yīng)用程序使用兩種機(jī)制連接到數(shù)據(jù)源:
1.DriverManager --- 這個(gè)類(lèi)在JDBC 1.0中引入,它使用硬編碼的URL來(lái)加載驅(qū)動(dòng)。
2.DataSource --- 這個(gè)接口在JDBC 2.0可選包中引入。它優(yōu)于DriverManager方式,因?yàn)樗[藏了數(shù)據(jù)源的詳細(xì)信息。我們通過(guò)設(shè)置DataSource的屬性來(lái)標(biāo)明它代表的數(shù)據(jù)源。當(dāng)getConnection方法被調(diào)用時(shí),DataSource對(duì)象會(huì)返回一個(gè)對(duì)應(yīng)的連接。我們可以通過(guò)改變DataSource的屬性來(lái)使它指向另一個(gè)數(shù)據(jù)源,而不是改變程序代碼。而且,即使DataSource的實(shí)現(xiàn)改變了,使用它的應(yīng)用程序代碼也不需要改變。
JDBC類(lèi)庫(kù)定義了兩個(gè)DataSource的擴(kuò)展來(lái)支持企業(yè)級(jí)應(yīng)用,如下:
1.ConnectionPoolDataSource --- 支持物理連接的緩存和重用,這樣可以提高應(yīng)用的性能和可伸縮性。
2.XADataSource --- 提供可以使用在分布式事務(wù)中的連接。
======================================================
4.2 執(zhí)行SQL語(yǔ)句和操縱結(jié)果
連接建立后,我們可以使用JDBC類(lèi)庫(kù)對(duì)目標(biāo)數(shù)據(jù)源進(jìn)行查詢(xún)和更新。JDBC類(lèi)庫(kù)提供了對(duì)大多數(shù)SQL2003通用特性的支持。由于各個(gè)廠商可能要支持不同的特性,JDBC類(lèi)庫(kù)提供了一個(gè)DatabaseMetadata接口。應(yīng)用可以通過(guò)這個(gè)接口了解數(shù)據(jù)源是否支持某個(gè)特性。JDBC類(lèi)庫(kù)也定義了轉(zhuǎn)義語(yǔ)義來(lái)支持特定廠商非標(biāo)準(zhǔn)的特性。轉(zhuǎn)義語(yǔ)義使得我們可以訪問(wèn)與本地程序相同的SQL特性集,同時(shí)保持應(yīng)用的可移植性。
應(yīng)用通過(guò)使用Connection接口來(lái)設(shè)置事務(wù)屬性和創(chuàng)建Statement,PreparedStatement和CallableStatement. 這些statement被用來(lái)執(zhí)行SQL語(yǔ)句和檢索結(jié)果。ResultSet接口封裝了SQL查詢(xún)的結(jié)果。語(yǔ)句也可以批處理,這樣應(yīng)用可以通過(guò)一次單元執(zhí)行提交對(duì)數(shù)據(jù)源的多次更新。
RowSet接口擴(kuò)展了ResultSet接口。它提供了一個(gè)比標(biāo)準(zhǔn)結(jié)果集功能更多的表數(shù)據(jù)容器。RowSet對(duì)象是Java Beans組件,它可以在中斷數(shù)據(jù)庫(kù)連接的情況下操縱數(shù)據(jù)。例如,一個(gè)RowSet實(shí)現(xiàn)可以被序列化從而傳送到網(wǎng)絡(luò)上,這對(duì)于吞吐量小的客戶(hù)端尤為有用,因?yàn)檫@可以省去加載JDBC驅(qū)動(dòng)和建立JDBC連接的開(kāi)銷(xiāo)。RowSet還可以使用定制的閱讀器(Reader)來(lái)訪問(wèn)表格數(shù)據(jù)(不僅僅是關(guān)系數(shù)據(jù)庫(kù)的數(shù)據(jù))。甚者,RowSet對(duì)象可以在中斷數(shù)據(jù)庫(kù)連接的情況下更新數(shù)據(jù),并在連接正常時(shí)通過(guò)一個(gè)定制的書(shū)寫(xiě)器(Writer)將更新寫(xiě)入數(shù)據(jù)源。
4.2.1 對(duì)SQL高級(jí)數(shù)據(jù)類(lèi)型的支持
JDBC類(lèi)庫(kù)定義了SQL數(shù)據(jù)類(lèi)型到JDBC數(shù)據(jù)類(lèi)型的標(biāo)準(zhǔn)映射。映射也包含了對(duì)SQL2003高級(jí)數(shù)據(jù)類(lèi)型如BLOB,CLOB,ARRAY,REF,STRUCT和DISTINCT的支持。JDBC驅(qū)動(dòng)也可以實(shí)現(xiàn)多個(gè)用戶(hù)自定義類(lèi)型(UDTs,user-defined types)的映射,在這里,每個(gè)UDT映射到Java中的一個(gè)類(lèi)。
JDBC類(lèi)庫(kù)也提供對(duì)外部數(shù)據(jù)的支持,例如數(shù)據(jù)源外部的一個(gè)文件。
========================================
4.3 兩層模型
兩層模型將功能分配到客戶(hù)端和服務(wù)器端,如圖4-1.

FIGURE 4-1 兩層模型
客戶(hù)端包含了應(yīng)用和一個(gè)或多個(gè)JDBC驅(qū)動(dòng),這些應(yīng)用負(fù)責(zé)下列內(nèi)容:
* 表示邏輯
* 業(yè)務(wù)邏輯
* 對(duì)多語(yǔ)句事務(wù)(multiple-statement transactions)或分布式事務(wù)的管理
* 資源管理
在這個(gè)模型中,應(yīng)用直接跟JDBC驅(qū)動(dòng)打交道,包括建立和管理物理連接,以及處理底層數(shù)據(jù)源的相關(guān)細(xì)節(jié)。應(yīng)用可以通過(guò)對(duì)數(shù)據(jù)源實(shí)現(xiàn)的了解來(lái)使用它的非標(biāo)準(zhǔn)特性或者提升性能。
模型的缺點(diǎn):
* 將表示邏輯、業(yè)務(wù)邏輯和基礎(chǔ)設(shè)施、系統(tǒng)級(jí)別的功能混淆在一起,不利于維護(hù)。
* 由于被綁定到特定的數(shù)據(jù)庫(kù),應(yīng)用很難被移植。需要連接到多個(gè)數(shù)據(jù)庫(kù)的應(yīng)用要注意各個(gè)廠商實(shí)現(xiàn)的區(qū)別。
* 缺少可伸縮性。典型地,應(yīng)用將從始至終占有一個(gè)或多個(gè)物理連接,缺少對(duì)并發(fā)應(yīng)用的支持。在這個(gè)模型中,性能、可伸縮性和可靠性問(wèn)題都是由JDBC驅(qū)動(dòng)和底層數(shù)據(jù)源處理的。如果應(yīng)用要跟多個(gè)驅(qū)動(dòng)打交道,它需要注意每個(gè)驅(qū)動(dòng)/數(shù)據(jù)源對(duì)是怎么處理這些問(wèn)題的。
======================================================
4.4 三層模型
三層模型引入了中間層服務(wù)器來(lái)管理業(yè)務(wù)邏輯和基礎(chǔ)結(jié)構(gòu),如圖4-2.

FIGURE 4-2 三層模型
這個(gè)架構(gòu)為企業(yè)級(jí)應(yīng)用提供了更好的性能、可伸縮性和可靠性。功能劃分如下:
1.客戶(hù)端 --- 只負(fù)責(zé)表示邏輯,處理人機(jī)交互。Java應(yīng)用程序、網(wǎng)頁(yè)瀏覽器和PDA等都是典型的客戶(hù)端。客戶(hù)端與中間層應(yīng)用交互,它不需要了解底層的基礎(chǔ)結(jié)構(gòu)和數(shù)據(jù)源實(shí)現(xiàn)。
2.中間層服務(wù)器 --- 中間層包含:
* 一些應(yīng)用程序。這些應(yīng)用負(fù)責(zé)跟客戶(hù)端打交道和實(shí)現(xiàn)業(yè)務(wù)邏輯。如果應(yīng)用包含與數(shù)據(jù)源的交互,它應(yīng)該使用高層抽象,例如DataSource對(duì)象和邏輯連接,而不是底層的驅(qū)動(dòng)程序類(lèi)庫(kù)。
* 一個(gè)應(yīng)用服務(wù)器。提供支持大部分應(yīng)用的基礎(chǔ)結(jié)構(gòu)。這可能包含管理和池化物理連接、管理事務(wù)和掩蓋不同JDBC驅(qū)動(dòng)的細(xì)節(jié)。最后一點(diǎn)使得應(yīng)用更容易被移植。應(yīng)用服務(wù)器可以使用J2EE服務(wù)器。它應(yīng)該直接和JDBC驅(qū)動(dòng)交互和提供高層應(yīng)用使用的功能抽象。
* 一個(gè)或多個(gè)JDBC驅(qū)動(dòng)。提供與底層數(shù)據(jù)源的連接,每個(gè)驅(qū)動(dòng)使用底層數(shù)據(jù)源支持的特性來(lái)實(shí)現(xiàn)標(biāo)準(zhǔn)JDBC類(lèi)庫(kù)。驅(qū)動(dòng)層需要掩蓋SQL2003標(biāo)準(zhǔn)和底層數(shù)據(jù)源語(yǔ)言的不同。如果數(shù)據(jù)源不是一個(gè)關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(DBMS),那么驅(qū)動(dòng)要實(shí)現(xiàn)應(yīng)用服務(wù)器使用的關(guān)系層。
3.底層數(shù)據(jù)源 --- 存放數(shù)據(jù)的層。包含關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng)(relational DBMS),遺留文件系統(tǒng),面向?qū)ο蟮腄BMS,數(shù)據(jù)倉(cāng)庫(kù),報(bào)表或者其他包裝和表示數(shù)據(jù)的方式,只要有對(duì)應(yīng)的支持JDBC類(lèi)庫(kù)的驅(qū)動(dòng)。
===================================================
4.5 J2EE平臺(tái)中的JDBC
J2EE組件,例如JSP,Servlets和EJB,經(jīng)常需要利用JDBC類(lèi)庫(kù)訪問(wèn)關(guān)系型數(shù)據(jù)。當(dāng)在J2EE組件里使用JDBC類(lèi)庫(kù)時(shí),容器可能幫你管理事務(wù)和數(shù)據(jù)源(譯者注:Container Managed Persistence,容器管理持久性)。這樣,J2EE組件開(kāi)發(fā)者就不直接使用JDBC類(lèi)庫(kù)的事務(wù)和數(shù)據(jù)源管理功能。詳情請(qǐng)見(jiàn)J2EE平臺(tái)規(guī)范。
版權(quán)所有 羅明