如何建立JDBC連接?
Connection 對象代表與數(shù)據(jù)庫的連接。連接過程包括所執(zhí)行的 SQL 語句和在該連接上所返回的結(jié)果。一個應(yīng)用程序可與單個數(shù)據(jù)庫有一個或多個連接,或者可與許多數(shù)據(jù)庫有連接。
1. 打開連接
與數(shù)據(jù)庫建立連接的標準方法是調(diào)用DriverManager.getConnection方法。該方法接受含有某個URL的字符串。DriverManager類(即所謂的JDBC管理層)將嘗試找到可與那個URL所代表的數(shù)據(jù)庫進行連接的驅(qū)動程序。DriverManager類存有已注冊的Driver類的清單。當調(diào)用方法getConnection時,它將檢查清單中的每個驅(qū)動程序,直到找到可與URL中指定的數(shù)據(jù)庫進行連接的驅(qū)動程序為止。Driver的方法connect使用這個URL來建立實際的連接。
用戶可繞過JDBC管理層直接調(diào)用Driver方法。這在以下特殊情況下將很有用:當兩個驅(qū)動器可同時連接到數(shù)據(jù)庫中,而用戶需要明確地選用其中特定的驅(qū)動器。但一般情況下,讓DriverManager類處理打開連接這種事將更為簡單。
下述代碼顯示如何打開一個與位于URL"jdbc:odbc:wombat"的數(shù)據(jù)庫的連接。所用的用戶標識符為"freely",口令為"ec":
String url = "jdbc:odbc:wombat"; Connection con = DriverManager.getConnection(url, "freely", "ec");
2. 一般用法的URL
由于URL常引起混淆,我們將先對一般URL作簡單說明,然后再討論JDBCURL。URL(統(tǒng)一資源定位符)提供在Internet上定位資源所需的信息。可將它想象為一個地址。URL的第一部份指定了訪問信息所用的協(xié)議,后面總是跟著冒號。常用的協(xié)議有"ftp"(代表"文件傳輸協(xié)議")和"http"(代表"超文本傳輸協(xié)議")。如果協(xié)議是"file",表示資源是在某個本地文件系統(tǒng)上而非在Internet上(下例用于表示我們所描述的部分;它并非URL的組成部分)。
ftp://Javasoft.com/docs/JDK-1_apidocs.zip http://Java.sun.com/products/jdk/CurrentRelease file:/home/haroldw/docs/books/tutorial/summary.html
URL的其余部份(冒號后面的)給出了數(shù)據(jù)資源所處位置的有關(guān)信息。如果協(xié)議是file,則URL的其余部份是文件的路徑。對于ftp和http協(xié)議,URL的其余部份標識了主機并可選地給出某個更詳盡的地址路徑。例如,以下是JavaSoft主頁的URL。該URL只標識了主機:http://Java.sun.com。從該主頁開始瀏覽,就可以進到許多其它的網(wǎng)頁中,其中之一就是JDBC主頁。JDBC主頁的URL更為具體,它具體表示為: http://Java.sun.com/products/jdbc
3. JDBC URL
JDBC URL提供了一種標識數(shù)據(jù)庫的方法,可以使相應(yīng)的驅(qū)動程序能識別該數(shù)據(jù)庫并與之建立連接。實際上,驅(qū)動程序編程員將決定用什么JDBC URL來標識特定的驅(qū)動程序。用戶不必關(guān)心如何來形成JDBC URL;他們只須使用與所用的驅(qū)動程序一起提供的URL即可。JDBC的作用是提供某些約定,驅(qū)動程序編程員在構(gòu)造他們的JDBC URL時應(yīng)該遵循這些約定。
由于JDBC URL要與各種不同的驅(qū)動程序一起使用,因此這些約定應(yīng)非常靈活。首先,它們應(yīng)允許不同的驅(qū)動程序使用不同的方案來命名數(shù)據(jù)庫。例如,odbc子協(xié)議允許(但并不是要求)URL含有屬性值。
其次,JDBC URL應(yīng)允許驅(qū)動程序編程員將一切所需的信息編入其中。這樣就可以讓要與給定數(shù)據(jù)庫對話的applet打開數(shù)據(jù)庫連接,而無須要求用戶去做任何系統(tǒng)管理工作。
最后,JDBC URL應(yīng)允許某種程度的間接性。也就是說,JDBC URL可指向邏輯主機或數(shù)據(jù)庫名,而這種邏輯主機或數(shù)據(jù)庫名將由網(wǎng)絡(luò)命名系統(tǒng)動態(tài)地轉(zhuǎn)換為實際的名稱。這可以使系統(tǒng)管理員不必將特定主機聲明為JDBC名稱的一部份。網(wǎng)絡(luò)命名服務(wù)(例如DNS、NIS和DCE)有多種,而對于使用哪種命名服務(wù)并無限制。 JDBC URL的標準語法如下所示。它由三部分組成,各部分間用冒號分隔: jdbc:<子協(xié)遙荊海甲用?稱??br> JDBC URL的三個部分可分解如下:
(1)jdbc協(xié)議:JDBC URL中的協(xié)議總是jdbc。
(2)<子協(xié)議>:驅(qū)動程序名或數(shù)據(jù)庫連接機制(這種機制可由一個或多個驅(qū)動程序支持)的名稱。子協(xié)議名的典型示例是"odbc",該名稱是為用于指定ODBC風格的數(shù)據(jù)資源名稱的URL專門保留的。例如,為了通過JDBC-ODBC橋來訪問某個數(shù)據(jù)庫,可以用如下所示的URL:jdbc:odbc:book。本例中,子協(xié)議為"odbc",子名稱"book"是本地ODBC數(shù)據(jù)資源。如果要用網(wǎng)絡(luò)命名服務(wù)(這樣JDBC URL中的數(shù)據(jù)庫名稱不必是實際名稱),則命名服務(wù)可以作為子協(xié)議。例如,可用如下所示的URL:jdbc:dcenaming:accounts。本例中,該URL指定了本地DCE命名服務(wù)應(yīng)該將數(shù)據(jù)庫名稱"accounts"解析為更為具體的可用于連接真實數(shù)據(jù)庫的名稱。
(3)<子名稱>:種標識數(shù)據(jù)庫的方法。子名稱可以依不同的子協(xié)議而變化。它還可以有子名稱的子名稱(含有驅(qū)動程序編程員所選的任何內(nèi)部語法)。使用子名稱的目的是為定位數(shù)據(jù)庫提供足夠的信息。前例中,因為ODBC將提供其余部份的信息,因此用"book"就已足夠。然而,位于遠程服務(wù)器上的數(shù)據(jù)庫需要更多的信息。例如,如果數(shù)據(jù)庫是通過Internet來訪問的,則在JDBC URL中應(yīng)將網(wǎng)絡(luò)地址作為子名稱的一部份包括進去,且必須遵循如下所示的標準URL命名約定://主機名:端口/子協(xié)議。
假設(shè)"dbnet"是個用于將某個主機連接到Internet上的協(xié)議,則JDBC URL應(yīng)為:jdbc:dbnet://wombat:356/fred。
4. "odbc"子協(xié)議
子協(xié)議odbc是一種特殊情況。它是為用于指定ODBC風格的數(shù)據(jù)資源名稱的URL而保留的,并具有下列特性:允許在子名稱(數(shù)據(jù)資源名稱)后面指定任意多個屬性值。odbc子協(xié)議的完整語法為:
jdbc:odbc:<數(shù)據(jù)資源名稱>[;<屬性名>=<屬性值>],因此,以下都是合法的jdbc:odbc名稱: jdbc:odbc:qeor7 jdbc:odbc:wombat jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER jdbc:odbc:qeora;UID=kgh;PWD=fooey
5. 注冊子協(xié)議
驅(qū)動程序編程員可保留某個名稱以將之用作JDBC URL的子協(xié)議名。當DriverManager類將此名稱加到已注冊的驅(qū)動程序清單中時,為之保留該名稱的驅(qū)動程序應(yīng)能識別該名稱并與它所標識的數(shù)據(jù)庫建立連接。例如,odbc是為JDBC-ODBC橋而保留的。假設(shè)有個Miracle公司,它可能會將"miracle"注冊為連接到其Miracle DBMS上的JDBC驅(qū)動程序的子協(xié)議,從而使其他人都無法使用這個名稱。
JavaSoft目前作為非正式代理負責注冊JDBC子協(xié)議名稱。要注冊某個子協(xié)議名稱,請發(fā)送電子郵件到下述地址:jdbc@wombat.eng.sun.com。
6. 發(fā)送SQL語句
連接一旦建立,就可用來向它所涉及的數(shù)據(jù)庫傳送SQL語句。JDBC對可被發(fā)送的SQL語句類型不加任何限制。這就提供了很大的靈活性,即允許使用特定的數(shù)據(jù)庫語句或甚至于非SQL語句。然而,它要求用戶自己負責確保所涉及的數(shù)據(jù)庫可以處理所發(fā)送的SQL語句,否則將自食其果。例如,如果某個應(yīng)用程序試圖向不支持儲存程序的DBMS發(fā)送儲存程序調(diào)用,就會失敗并將拋出異常。JDBC要求驅(qū)動程序應(yīng)至少能提供ANSI SQL-2 Entry Level功能才可算是符合JDBC標準TM的。這意味著用戶至少可信賴這一標準級別的功能。
JDBC提供了三個類,用于向數(shù)據(jù)庫發(fā)送SQL語句。Connection接口中的三個方法可用于創(chuàng)建這些類的實例。下面列出這些類及其創(chuàng)建方法:
(1)Statement:由方法createStatement所創(chuàng)建。Statement對象用于發(fā)送簡單的SQL語句。
(2)PreparedStatement:由方法prepareStatement所創(chuàng)建。PreparedStatement對象用于發(fā)送帶有一個或多個輸入?yún)?shù)(IN參數(shù))的SQL語句。PreparedStatement擁有一組方法,用于設(shè)置IN參數(shù)的值。執(zhí)行語句時,這些IN參數(shù)將被送到數(shù)據(jù)庫中。PreparedStatement的實例擴展了Statement,因此它們都包括了Statement的方法。PreparedStatement對象有可能比Statement對象的效率更高,因為它已被預(yù)編譯過并存放在那以供將來使用。
(3)CallableStatement:由方法prepareCall所創(chuàng)建。CallableStatement對象用于執(zhí)行SQL儲存程序─一組可通過名稱來調(diào)用(就象函數(shù)的調(diào)用那樣)的SQL語句。CallableStatement對象從PreparedStatement中繼承了用于處理IN參數(shù)的方法,而且還增加了用于處理OUT參數(shù)和INOUT參數(shù)的方法。
不過通常來說createStatement方法用于簡單的SQL語句(不帶參數(shù))、prepareStatement方法用于帶一個或多個IN參數(shù)的SQL語句或經(jīng)常被執(zhí)行的簡單SQL語句,而prepareCall方法用于調(diào)用已儲存過程。
7. 事務(wù)
事務(wù)由一個或多個這樣的語句組成:這些語句已被執(zhí)行、完成并被提交或還原。當調(diào)用方法commit或rollback時,當前事務(wù)即告就結(jié)束,另一個事務(wù)隨即開始。缺省情況下,新連接將處于自動提交模式。也就是說,當執(zhí)行完語句后,將自動對那個語句調(diào)用commit方法。這種情況下,由于每個語句都是被單獨提交的,因此一個事務(wù)只由一個語句組成。如果禁用自動提交模式,事務(wù)將要等到commit或rollback方法被顯式調(diào)用時才結(jié)束,因此它將包括上一次調(diào)用commit或rollback方法以來所有執(zhí)行過的語句。對于第二種情況,事務(wù)中的所有語句將作為組來提交或還原。
方法commit使SQL語句對數(shù)據(jù)庫所做的任何更改成為永久性的,它還將釋放事務(wù)持有的全部鎖。而方法rollback將棄去那些更改。有時用戶在另一個更改生效前不想讓此更改生效。這可通過禁用自動提交并將兩個更新組合在一個事務(wù)中來達到。如果兩個更新都是成功,則調(diào)用commit方法,從而使兩個更新結(jié)果成為永久性的;如果其中之一或兩個更新都失敗了,則調(diào)用rollback方法,以將值恢復(fù)為進行更新之前的值。
大多數(shù)JDBC驅(qū)動程序都支持事務(wù)。事實上,符合JDBC的驅(qū)動程序必須支持事務(wù)。DatabaseMetaData給出的信息描述DBMS所提供的事務(wù)支持水平。
8. 事務(wù)隔離級別
如果DBMS支持事務(wù)處理,它必須有某種途徑來管理兩個事務(wù)同時對一個數(shù)據(jù)庫進行操作時可能發(fā)生的沖突。用戶可指定事務(wù)隔離級別,以指明DBMS應(yīng)該花多大精力來解決潛在沖突。例如,當事務(wù)更改了某個值而第二個事務(wù)卻在該更改被提交或還原前讀取該值時該怎么辦。
假設(shè)第一個事務(wù)被還原后,第二個事務(wù)所讀取的更改值將是無效的,那么是否可允許這種沖突?JDBC用戶可用以下代碼來指示DBMS允許在值被提交前讀取該值("dirty讀取"),其中con是當前連接: con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);
事務(wù)隔離級別越高,為避免沖突所花的精力也就越多。Connection接口定義了五級,其中最低級別指定了根本就不支持事務(wù),而最高級別則指定當事務(wù)在對某個數(shù)據(jù)庫進行操作時,任何其它事務(wù)不得對那個事務(wù)正在讀取的數(shù)據(jù)進行任何更改。通常,隔離級別越高,應(yīng)用程序執(zhí)行的速度也就越慢(由于用于鎖定的資源耗費增加了,而用戶間的并發(fā)操作減少了)。在決定采用什么隔離級別時,開發(fā)人員必須在性能需求和數(shù)據(jù)一致性需求之間進行權(quán)衡。當然,實際所能支持的級別取決于所涉及的DBMS的功能。
當創(chuàng)建Connection對象時,其事務(wù)隔離級別取決于驅(qū)動程序,但通常是所涉及的數(shù)據(jù)庫的缺省值。用戶可通過調(diào)用setIsolationLevel方法來更改事務(wù)隔離級別。新的級別將在該連接過程的剩余時間內(nèi)生效。要想只改變一個事務(wù)的事務(wù)隔離級別,必須在該事務(wù)開始前進行設(shè)置,并在該事務(wù)結(jié)束后進行復(fù)位。我們不提倡在事務(wù)的中途對事務(wù)隔離級別進行更改,因為這將立即觸發(fā)commit方法的調(diào)用,使在此之前所作的任何更改變成永久性的。 |
|