免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
JR 精品文章 - 全面解析JDBC<一>
綜述:Java數(shù)據(jù)庫連接體系結(jié)構(gòu)是用于Java應用程序連接數(shù)據(jù)庫的標準方法。JDBC對Java程序員而言是API,對實現(xiàn)與數(shù)據(jù)庫連接的服務提供商而言是接口模型。作為API,JDBC為程序開發(fā)提供標準的接口,并為數(shù)據(jù)庫廠商及第三方中間件廠商實現(xiàn)與數(shù)據(jù)庫的連接提供了標準方法。JDBC使用已有的SQL標準并支持與其它數(shù)據(jù)庫連接標準,如ODBC之間的橋接。JDBC實現(xiàn)了所有這些面向標準的目標并且具有簡單、嚴格類型定義且高性能實現(xiàn)的接口。

  如何選擇合適的JDBC產(chǎn)品?

  有關JDBC最新的信息,有興趣的讀者可以查閱JDBC的官方網(wǎng)站--即JavaSoft的主頁,其URL為:http://Java.sun.com/products/jdbc

  1. JavaSoft框架

  JavaSoft提供三種JDBC產(chǎn)品組件,它們是Java開發(fā)工具包(JDK)的組成部份:JDBC驅(qū)動程序管理器、JDBC驅(qū)動程序測試工具包和JDBC-ODBC橋。

  JDBC驅(qū)動程序管理器是JDBC體系結(jié)構(gòu)的支柱。它實際上很小,也很簡單;其主要作用是把Java應用程序連接到正確的JDBC驅(qū)動程序上,然后即退出。

  JDBC驅(qū)動程序測試工具包為使JDBC驅(qū)動程序運行您的程序提供一定的可信度。只有通過JDBC驅(qū)動程序測試的驅(qū)動程序才被認為是符合JDBC標準TM的。

  JDBC-ODBC橋使ODBC驅(qū)動程序可被用作JDBC驅(qū)動程序。它的實現(xiàn)為JDBC的快速發(fā)展提供了一條途徑,其長遠目標提供一種訪問某些不常見的DBMS(如果對這些不常見的DBMS未實現(xiàn)JDBC)的方法。

  2. JDBC驅(qū)動程序的類型

  目前比較常見的JDBC驅(qū)動程序可分為以下四個種類:

 ?。?)JDBC-ODBC橋加ODBC驅(qū)動程序

  JavaSoft橋產(chǎn)品利用ODBC驅(qū)動程序提供JDBC訪問。注意,必須將ODBC二進制代碼(許多情況下還包括數(shù)據(jù)庫客戶機代碼)加載到使用該驅(qū)動程序的每個客戶機上。因此,這種類型的驅(qū)動程序最適合于企業(yè)網(wǎng)(這種網(wǎng)絡上客戶機的安裝不是主要問題),或者是用Java編寫的三層結(jié)構(gòu)的應用程序服務器代碼。

 ?。?)本地API

  這種類型的驅(qū)動程序把客戶機API上的JDBC調(diào)用轉(zhuǎn)換為Oracle、Sybase、Informix、DB2或其它DBMS的調(diào)用。注意,象橋驅(qū)動程序一樣,這種類型的驅(qū)動程序要求將某些二進制代碼加載到每臺客戶機上。

 ?。?)JDBC網(wǎng)絡純Java驅(qū)動程序

  這種驅(qū)動程序?qū)DBC轉(zhuǎn)換為與DBMS無關的網(wǎng)絡協(xié)議,之后這種協(xié)議又被某個服務器轉(zhuǎn)換為一種DBMS協(xié)議。這種網(wǎng)絡服務器中間件能夠?qū)⑺募僇ava客戶機連接到多種不同的數(shù)據(jù)庫上。所用的具體協(xié)議取決于提供者。通常,這是最為靈活的JDBC驅(qū)動程序。有可能所有這種解決方案的提供者都提供適合于Intranet用的產(chǎn)品。為了使這些產(chǎn)品也支持Internet訪問,它們必須處理Web所提出的安全性、通過防火墻的訪問等方面的額外要求。幾家提供者正將JDBC驅(qū)動程序加到他們現(xiàn)有的數(shù)據(jù)庫中間件產(chǎn)品中。

 ?。?)本地協(xié)議純Java驅(qū)動程序

  這種類型的驅(qū)動程序?qū)DBC調(diào)用直接轉(zhuǎn)換為DBMS所使用的網(wǎng)絡協(xié)議。這將允許從客戶機機器上直接調(diào)用DBMS服務器,是Intranet訪問的一個很實用的解決方法。由于許多這樣的協(xié)議都是專用的,因此數(shù)據(jù)庫提供者自己將是主要來源,有幾家提供者已在著手做這件事了。

  據(jù)專家預計第(3)、(4)類驅(qū)動程序?qū)⒊蔀閺腏DBC訪問數(shù)據(jù)庫的首方法。第(1)、(2)類驅(qū)動程序在直接的純Java驅(qū)動程序還沒有上市前會作為過渡方案來使用。對第(1)、(2)類驅(qū)動程序可能會有一些變種,這些變種要求有連接器,但通常這些是更加不可取的解決方案。第(3)、(4)類驅(qū)動程序提供了Java的所有優(yōu)點,包括自動安裝(例如,通過使用JDBC驅(qū)動程序的appletapplet來下載該驅(qū)動程序)。

  3. JDBC驅(qū)動程序的獲取



  目前已有幾十個(1)類的驅(qū)動程序,即可與Javasoft橋聯(lián)合使用的ODBC驅(qū)動程序的驅(qū)動程序。有大約十多個屬于種類(2)的驅(qū)動程序是以DBMS的本地API為基礎編寫的。只有幾個屬于種類(3)的驅(qū)動程序,其首批提供者是SCO、OpenHorizon、Visigenic和WebLogic。此外,JavaSoft和數(shù)據(jù)庫連接的領先提供者Intersolv還合作研制了JDBC-ODBC橋和JDBC驅(qū)動程序測試工具包。

 
如何建立JDBC連接?

  Connection 對象代表與數(shù)據(jù)庫的連接。連接過程包括所執(zhí)行的 SQL 語句和在該連接上所返回的結(jié)果。一個應用程序可與單個數(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ù)資源所處位置的有關信息。如果協(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ù)庫的方法,可以使相應的驅(qū)動程序能識別該數(shù)據(jù)庫并與之建立連接。實際上,驅(qū)動程序編程員將決定用什么JDBC URL來標識特定的驅(qū)動程序。用戶不必關心如何來形成JDBC URL;他們只須使用與所用的驅(qū)動程序一起提供的URL即可。JDBC的作用是提供某些約定,驅(qū)動程序編程員在構(gòu)造他們的JDBC URL時應該遵循這些約定。

  由于JDBC URL要與各種不同的驅(qū)動程序一起使用,因此這些約定應非常靈活。首先,它們應允許不同的驅(qū)動程序使用不同的方案來命名數(shù)據(jù)庫。例如,odbc子協(xié)議允許(但并不是要求)URL含有屬性值。 

  其次,JDBC URL應允許驅(qū)動程序編程員將一切所需的信息編入其中。這樣就可以讓要與給定數(shù)據(jù)庫對話的applet打開數(shù)據(jù)庫連接,而無須要求用戶去做任何系統(tǒng)管理工作。

  最后,JDBC URL應允許某種程度的間接性。也就是說,JDBC URL可指向邏輯主機或數(shù)據(jù)庫名,而這種邏輯主機或數(shù)據(jù)庫名將由網(wǎng)絡命名系統(tǒng)動態(tài)地轉(zhuǎn)換為實際的名稱。這可以使系統(tǒng)管理員不必將特定主機聲明為JDBC名稱的一部份。網(wǎng)絡命名服務(例如DNS、NIS和DCE)有多種,而對于使用哪種命名服務并無限制。
JDBC URL的標準語法如下所示。它由三部分組成,各部分間用冒號分隔:
jdbc:<子協(xié)遙荊海甲用?疲?br>   JDBC URL的三個部分可分解如下:

  (1)jdbc協(xié)議:JDBC URL中的協(xié)議總是jdbc。

 ?。?)<子協(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)絡命名服務(這樣JDBC URL中的數(shù)據(jù)庫名稱不必是實際名稱),則命名服務可以作為子協(xié)議。例如,可用如下所示的URL:jdbc:dcenaming:accounts。本例中,該URL指定了本地DCE命名服務應該將數(shù)據(jù)庫名稱"accounts"解析為更為具體的可用于連接真實數(shù)據(jù)庫的名稱。

  (3)<子名稱>:種標識數(shù)據(jù)庫的方法。子名稱可以依不同的子協(xié)議而變化。它還可以有子名稱的子名稱(含有驅(qū)動程序編程員所選的任何內(nèi)部語法)。使用子名稱的目的是為定位數(shù)據(jù)庫提供足夠的信息。前例中,因為ODBC將提供其余部份的信息,因此用"book"就已足夠。然而,位于遠程服務器上的數(shù)據(jù)庫需要更多的信息。例如,如果數(shù)據(jù)庫是通過Internet來訪問的,則在JDBC URL中應將網(wǎng)絡地址作為子名稱的一部份包括進去,且必須遵循如下所示的標準URL命名約定://主機名:端口/子協(xié)議。

  假設"dbnet"是個用于將某個主機連接到Internet上的協(xié)議,則JDBC URL應為: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ū)動程序應能識別該名稱并與它所標識的數(shù)據(jù)庫建立連接。例如,odbc是為JDBC-ODBC橋而保留的。假設有個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語句,否則將自食其果。例如,如果某個應用程序試圖向不支持儲存程序的DBMS發(fā)送儲存程序調(diào)用,就會失敗并將拋出異常。JDBC要求驅(qū)動程序應至少能提供ANSI SQL-2 Entry Level功能才可算是符合JDBC標準TM的。這意味著用戶至少可信賴這一標準級別的功能。

  JDBC提供了三個類,用于向數(shù)據(jù)庫發(fā)送SQL語句。Connection接口中的三個方法可用于創(chuàng)建這些類的實例。下面列出這些類及其創(chuàng)建方法:

 ?。?)Statement:由方法createStatement所創(chuàng)建。Statement對象用于發(fā)送簡單的SQL語句。

  (2)PreparedStatement:由方法prepareStatement所創(chuàng)建。PreparedStatement對象用于發(fā)送帶有一個或多個輸入?yún)?shù)(IN參數(shù))的SQL語句。PreparedStatement擁有一組方法,用于設置IN參數(shù)的值。執(zhí)行語句時,這些IN參數(shù)將被送到數(shù)據(jù)庫中。PreparedStatement的實例擴展了Statement,因此它們都包括了Statement的方法。PreparedStatement對象有可能比Statement對象的效率更高,因為它已被預編譯過并存放在那以供將來使用。

  (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. 事務

  事務由一個或多個這樣的語句組成:這些語句已被執(zhí)行、完成并被提交或還原。當調(diào)用方法commit或rollback時,當前事務即告就結(jié)束,另一個事務隨即開始。缺省情況下,新連接將處于自動提交模式。也就是說,當執(zhí)行完語句后,將自動對那個語句調(diào)用commit方法。這種情況下,由于每個語句都是被單獨提交的,因此一個事務只由一個語句組成。如果禁用自動提交模式,事務將要等到commit或rollback方法被顯式調(diào)用時才結(jié)束,因此它將包括上一次調(diào)用commit或rollback方法以來所有執(zhí)行過的語句。對于第二種情況,事務中的所有語句將作為組來提交或還原。

  方法commit使SQL語句對數(shù)據(jù)庫所做的任何更改成為永久性的,它還將釋放事務持有的全部鎖。而方法rollback將棄去那些更改。有時用戶在另一個更改生效前不想讓此更改生效。這可通過禁用自動提交并將兩個更新組合在一個事務中來達到。如果兩個更新都是成功,則調(diào)用commit方法,從而使兩個更新結(jié)果成為永久性的;如果其中之一或兩個更新都失敗了,則調(diào)用rollback方法,以將值恢復為進行更新之前的值。

  大多數(shù)JDBC驅(qū)動程序都支持事務。事實上,符合JDBC的驅(qū)動程序必須支持事務。DatabaseMetaData給出的信息描述DBMS所提供的事務支持水平。

  8. 事務隔離級別

  如果DBMS支持事務處理,它必須有某種途徑來管理兩個事務同時對一個數(shù)據(jù)庫進行操作時可能發(fā)生的沖突。用戶可指定事務隔離級別,以指明DBMS應該花多大精力來解決潛在沖突。例如,當事務更改了某個值而第二個事務卻在該更改被提交或還原前讀取該值時該怎么辦。

  假設第一個事務被還原后,第二個事務所讀取的更改值將是無效的,那么是否可允許這種沖突?JDBC用戶可用以下代碼來指示DBMS允許在值被提交前讀取該值("dirty讀取"),其中con是當前連接:
con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);

  事務隔離級別越高,為避免沖突所花的精力也就越多。Connection接口定義了五級,其中最低級別指定了根本就不支持事務,而最高級別則指定當事務在對某個數(shù)據(jù)庫進行操作時,任何其它事務不得對那個事務正在讀取的數(shù)據(jù)進行任何更改。通常,隔離級別越高,應用程序執(zhí)行的速度也就越慢(由于用于鎖定的資源耗費增加了,而用戶間的并發(fā)操作減少了)。在決定采用什么隔離級別時,開發(fā)人員必須在性能需求和數(shù)據(jù)一致性需求之間進行權(quán)衡。當然,實際所能支持的級別取決于所涉及的DBMS的功能。

  當創(chuàng)建Connection對象時,其事務隔離級別取決于驅(qū)動程序,但通常是所涉及的數(shù)據(jù)庫的缺省值。用戶可通過調(diào)用setIsolationLevel方法來更改事務隔離級別。新的級別將在該連接過程的剩余時間內(nèi)生效。要想只改變一個事務的事務隔離級別,必須在該事務開始前進行設置,并在該事務結(jié)束后進行復位。我們不提倡在事務的中途對事務隔離級別進行更改,因為這將立即觸發(fā)commit方法的調(diào)用,使在此之前所作的任何更改變成永久性的。
JDBC驅(qū)動管理內(nèi)幕是怎么樣的?

  DriverManager 類是 JDBC 的管理層,作用于用戶和驅(qū)動程序之間。它跟蹤可用的驅(qū)動程序,并在數(shù)據(jù)庫和相應驅(qū)動程序之間建立連接。另外,DriverManager類也處理諸如驅(qū)動程序登錄時間限制及登錄和跟蹤消息的顯示等事務。 

  對于簡單的應用程序,一般程序員需要在此類中直接使用的唯一方法是DriverManager.getConnection。正如名稱所示,該方法將建立與數(shù)據(jù)庫的連接。JDBC允許用戶調(diào)用DriverManager的方法getDriver、getDrivers和registerDriver及Driver的方法connect。但多數(shù)情況下,讓DriverManager類管理建立連接的細節(jié)為上策。

  1. 跟蹤可用驅(qū)動程序

  DriverManager類包含一列Driver類,它們已通過調(diào)用方法DriverManager.registerDriver對自己進行了注冊。所有Driver類都必須包含有一個靜態(tài)部分。它創(chuàng)建該類的實例,然后在加載該實例時DriverManager類進行注冊。這樣,用戶正常情況下將不會直接調(diào)用DriverManager.registerDriver;而是在加載驅(qū)動程序時由驅(qū)動程序自動調(diào)用。加載Driver類,然后自動在DriverManager中注冊的方式有兩種:

  (1)調(diào)用方法Class.forName

  這將顯式地加載驅(qū)動程序類。由于這與外部設置無關,因此推薦使用這種加載驅(qū)動程序的方法。以下代碼加載類acme.db.Driver:Class.forName("acme.db.Driver")。

  如果將acme.db.Driver編寫為加載時創(chuàng)建實例,并調(diào)用以該實例為參數(shù)的DriverManager.registerDriver(本該如此),則它在DriverManager的驅(qū)動程序列表中,并可用于創(chuàng)建連接。

 ?。?)將驅(qū)動程序添加到Java.lang.System的屬性jdbc.drivers中

  這是一個由DriverManager類加載的驅(qū)動程序類名的列表,由冒號分隔:初始化DriverManager類時,它搜索系統(tǒng)屬性jdbc.drivers,如果用戶已輸入了一個或多個驅(qū)動程序,則DriverManager類將試圖加載它們。以下代碼說明程序員如何在~/.hotJava/properties中輸入三個驅(qū)動程序類(啟動時,HotJava將把它加載到系統(tǒng)屬性列表中):

  jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.test.ourDriver;

  對DriverManager方法的第一次調(diào)用將自動加載這些驅(qū)動程序類。注意:加載驅(qū)動程序的第二種方法需要持久的預設環(huán)境。如果對這一點不能保證,則調(diào)用方法Class.forName顯式地加載每個驅(qū)動程序就顯得更為安全。這也是引入特定驅(qū)動程序的方法,因為一旦DriverManager類被初始化,它將不再檢查jdbc.drivers屬性列表。

  在以上兩種情況中,新加載的Driver類都要通過調(diào)用DriverManager.registerDriver類進行自我注冊。如上所述,加載類時將自動執(zhí)行這一過程。

  由于安全方面的原因,JDBC管理層將跟蹤哪個類加載器提供哪個驅(qū)動程序。這樣,當DriverManager類打開連接時,它僅使用本地文件系統(tǒng)或與發(fā)出連接請求的代碼相同的類加載器提供的驅(qū)動程序。

  2. 建立連接

  加載Driver類并在DriverManager類中注冊后,它們即可用來與數(shù)據(jù)庫建立連接。當調(diào)用DriverManager.getConnection方法發(fā)出連接請求時,DriverManager將檢查每個驅(qū)動程序,查看它是否可以建立連接。

  有時可能有多個JDBC驅(qū)動程序可以與給定的URL連接。例如,與給定遠程數(shù)據(jù)庫連接時,可以使用JDBC-ODBC橋驅(qū)動程序、JDBC到通用網(wǎng)絡協(xié)議驅(qū)動程序或數(shù)據(jù)庫廠商提供的驅(qū)動程序。在這種情況下測試驅(qū)動程序的順序至關重要,因為DriverManager將使用它所找到的第一個可以成功連接到給定URL的驅(qū)動程序。

  首先DriverManager試圖按注冊的順序使用每個驅(qū)動程序(jdbc.drivers中列出的驅(qū)動程序總是先注冊)。它將跳過代碼不可信任的驅(qū)動程序,除非加載它們的源與試圖打開連接的代碼的源相同。它通過輪流在每個驅(qū)動程序上調(diào)用方法Driver.connect,并向它們傳遞用戶開始傳遞給方法DriverManager.getConnection的URL來對驅(qū)動程序進行測試,然后連接第一個認出該URL的驅(qū)動程序。這種方法初看起來效率不高,但由于不可能同時加載數(shù)十個驅(qū)動程序,因此每次連接實際只需幾個過程調(diào)用和字符串比較。

  以下代碼是通常情況下用驅(qū)動程序(例如JDBC-ODBC橋驅(qū)動程序)建立連接所需所有步驟的示例:



Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");//加載驅(qū)動程序
String url = "jdbc:odbc:fred";
DriverManager.getConnection(url,"userID","passwd"); 
如何利用JDBC發(fā)送SQL語句?

  Statement對象用于將SQL語句發(fā)送到數(shù)據(jù)庫中。實際上有三種Statement對象,它們都作為在給定連接上執(zhí)行SQL語句的包容器:Statement、PreparedStatement(它從Statement繼承而來)和CallableStatement(它從PreparedStatement繼承而來)。它們都專用于發(fā)送特定類型的SQL語句:Statement對象用于執(zhí)行不帶參數(shù)的簡單SQL語句;PreparedStatement對象用于執(zhí)行帶或不帶IN參數(shù)的預編譯SQL語句;CallableStatement對象用于執(zhí)行對數(shù)據(jù)庫已存儲過程的調(diào)用。

  Statement接口提供了執(zhí)行語句和獲取結(jié)果的基本方法;PreparedStatement接口添加了處理IN參數(shù)的方法;而CallableStatement添加了處理OUT參數(shù)的方法。

  1. 創(chuàng)建Statement對象

  建立了到特定數(shù)據(jù)庫的連接之后,就可用該連接發(fā)送SQL語句。Statement對象用Connection的方法createStatement創(chuàng)建,如下列代碼段中所示:

Connection con = DriverManager.getConnection(url,"sunny","");
Statement stmt = con.createStatement();
 

  為了執(zhí)行Statement對象,被發(fā)送到數(shù)據(jù)庫的SQL語句將被作為參數(shù)提供給Statement的方法:

  ResultSet rs = stmt.executeQuery("SELECT a,b,c FROM Table2");

  2. 使用Statement對象執(zhí)行語句

  Statement接口提供了三種執(zhí)行SQL語句的方法:executeQuery、executeUpdate和execute。使用哪一個方法由SQL語句所產(chǎn)生的內(nèi)容決定。

  方法executeQuery用于產(chǎn)生單個結(jié)果集的語句,例如SELECT語句。方法executeUpdate用于執(zhí)行INSERT、UPDATE或DELETE語句以及SQL DDL(數(shù)據(jù)定義語言)語句,例如CREATE TABLE和DROP TABLE。INSERT、UPDATE或DELETE語句的效果是修改表中零行或多行中的一列或多列。executeUpdate的返回值是一個整數(shù),指示受影響的行數(shù)(即更新計數(shù))。對于CREATE TABLE或DROP TABLE等不操作行的語句,executeUpdate的返回值總為零。

  執(zhí)行語句的所有方法都將關閉所調(diào)用的Statement對象的當前打開結(jié)果集(如果存在)。這意味著在重新執(zhí)行Statement對象之前,需要完成對當前ResultSet對象的處理。應注意,繼承了Statement接口中所有方法的PreparedStatement接口都有自己的executeQuery、executeUpdate和execute方法。Statement對象本身不包含SQL語句,因而必須給Statement.execute方法提供SQL語句作為參數(shù)。PreparedStatement對象并不需要SQL語句作為參數(shù)提供給這些方法,因為它們已經(jīng)包含預編譯SQL語句。

  CallableStatement對象繼承這些方法的PreparedStatement形式。對于這些方法的PreparedStatement或CallableStatement版本,使用查詢參數(shù)將拋出SQLException。

  3. 語句完成

  當連接處于自動提交模式時,其中所執(zhí)行的語句在完成時將自動提交或還原。語句在已執(zhí)行且所有結(jié)果返回時,即認為已完成。對于返回一個結(jié)果集的executeQuery方法,在檢索完ResultSet對象的所有行時該語句完成。對于方法executeUpdate,當它執(zhí)行時語句即完成。但在少數(shù)調(diào)用方法execute的情況中,在檢索所有結(jié)果集或它生成的更新計數(shù)之后語句才完成。

  有些DBMS將已存儲過程中的每條語句視為獨立的語句;而另外一些則將整個過程視為一個復合語句。在啟用自動提交時,這種差別就變得非常重要,因為它影響什么時候調(diào)用commit方法。在前一種情況中,每條語句單獨提交;在后一種情況中,所有語句同時提交。

  4. 關閉Statement對象

  Statement對象將由Java垃圾收集程序自動關閉。而作為一種好的編程風格,應在不需要Statement對象時顯式地關閉它們。這將立即釋放DBMS資源,有助于避免潛在的內(nèi)存問題。

  5. 使用方法execute

  execute方法應該僅在語句能返回多個ResultSet對象、多個更新計數(shù)或ResultSet對象與更新計數(shù)的組合時使用。當執(zhí)行某個已存儲過程或動態(tài)執(zhí)行未知SQL字符串(即應用程序程序員在編譯時未知)時,有可能出現(xiàn)多個結(jié)果的情況,盡管這種情況很少見。例如,用戶可能執(zhí)行一個已存儲過程,并且該已存儲過程可執(zhí)行更新,然后執(zhí)行選擇,再進行更新,再進行選擇,等等。通常使用已存儲過程的人應知道它所返回的內(nèi)容。

  因為方法execute處理非常規(guī)情況,所以獲取其結(jié)果需要一些特殊處理并不足為怪。例如,假定已知某個過程返回兩個結(jié)果集,則在使用方法execute執(zhí)行該過程后,必須調(diào)用方法getResultSet獲得第一個結(jié)果集,然后調(diào)用適當?shù)膅etXXX方法獲取其中的值。要獲得第二個結(jié)果集,需要先調(diào)用getMoreResults方法,然后再調(diào)用getResultSet方法。如果已知某個過程返回兩個更新計數(shù),則首先調(diào)用方法getUpdateCount,然后調(diào)用getMoreResults,并再次調(diào)用getUpdateCount。

  對于不知道返回內(nèi)容,則情況更為復雜。如果結(jié)果是ResultSet對象,則方法execute返回true;如果結(jié)果是Javaint,則返回false。如果返回int,則意味著結(jié)果是更新計數(shù)或執(zhí)行的語句是DL命令。在調(diào)用方法execute之后要做的第一件事情是調(diào)用getResultSet或getUpdateCount。調(diào)用方法getResultSet可以獲得兩個或多個ResultSet對象中第一個對象;或調(diào)用方法getUpdateCount可以獲得兩個或多個更新計數(shù)中第一個更新計數(shù)的內(nèi)容。

  當SQL語句的結(jié)果不是結(jié)果集時,則方法getResultSet將返回null。這可能意味著結(jié)果是一個更新計數(shù)或沒有其它結(jié)果。在這種情況下,判斷null真正含義的唯一方法是調(diào)用方法getUpdateCount,它將返回一個整數(shù)。這個整數(shù)為調(diào)用語句所影響的行數(shù);如果為-1則表示結(jié)果是結(jié)果集或沒有結(jié)果。如果方法getResultSet已返回null(表示結(jié)果不是ResultSet對象),則返回值-1表示沒有其它結(jié)果。也就是說,當下列條件為真時表示沒有結(jié)果(或沒有其它結(jié)果): 

 ?。ǎ╯tmt.getResultSet()==null)&&(stmt.getUpdateCount()==-1))

  如果已經(jīng)調(diào)用方法getResultSet并處理了它返回的ResultSet對象,則有必要調(diào)用方法getMoreResults以確定是否有其它結(jié)果集或更新計數(shù)。如果getMoreResults返回true,則需要再次調(diào)用getResultSet來檢索下一個結(jié)果集。如上所述,如果getResultSet返回null,則需要調(diào)用getUpdateCount來檢查null是表示結(jié)果為更新計數(shù)還是表示沒有其它結(jié)果。

  當getMoreResults返回false時,它表示該SQL語句返回一個更新計數(shù)或沒有其它結(jié)果。因此需要調(diào)用方法getUpdateCount來檢查它是哪一種情況。在這種情況下,當下列條件為真時表示沒有其它結(jié)果:

 ?。ǎ╯tmt.getMoreResults()==false)&&(stmt.getUpdateCount()==-1))
本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
JDBC系列教程(一)---連接
jdbc
JSP漸進學習教程9
JAVA如何連接數(shù)據(jù)庫
使用JDBC連接數(shù)據(jù)庫 - 《Java JDK 6學習筆記》
JDBC連接數(shù)據(jù)庫過程
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服