<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 5  文章 - 2  trackbacks - 0
    <2006年11月>
    2930311234
    567891011
    12131415161718
    19202122232425
    262728293012
    3456789

    常用鏈接

    留言簿(1)

    隨筆分類

    隨筆檔案

    搜索

    •  

    最新評論

    閱讀排行榜

    評論排行榜

    JDBC專題介紹
    Ref:
    http://kb.csdn.net/java/Articles/200506/73344a78-6148-475b-b42f-ab03f95e95a8.html

    1.?介紹

      許多開發(fā)者和用戶都在尋找Java程序中訪問數(shù)據(jù)庫的便捷方法。由于Java是一個健壯,安全,易于使用的,易于理解且可以從網(wǎng)絡(luò)中自動download?,所以它成為開發(fā)數(shù)據(jù)庫應(yīng)用的一種良好的語言基礎(chǔ)。它提供了C,C++,Smalltalk,?BASIC,?COBOL,?and?4GLs的許多優(yōu)點。許多公司已經(jīng)開始在Java與DBMS的連接方面做工作。

      許多Java應(yīng)用開發(fā)者都希望能夠編寫?yīng)毩⒂谔囟―BMS的程序,而我們也相信一個獨立于DBMS的接口將使得與各種各樣DBMS連接變得最為便捷,開發(fā)更加迅速。所以我們認為定義一個通用的SQL數(shù)據(jù)庫存取框架,在各種各樣的提供數(shù)據(jù)庫連接模塊上提供統(tǒng)一的界面是十分有意義的。這使程序員可以面對單一的數(shù)據(jù)庫界面,使數(shù)據(jù)庫無關(guān)的Java工具和產(chǎn)品成為可能,使得數(shù)據(jù)庫連接的開發(fā)者可以提供各種各樣的連接方案。我們看到我們定義一個通用低層的,支持基本SQL功能的JavaDataBase?Connectivity?(JDBC)API的緊迫任務(wù)。

      幸運的是我們不必從頭設(shè)計一個SQL?API。我們可以把我們的工作建立在?X/Open?SQL?CLI?(調(diào)用層接口)之上(它也是Microsoft"s?ODBC?的基礎(chǔ))。

      我們主要任務(wù)是定義一個自然的Java接口來與X/Open?CLI中定義的基本的抽象層和概念連接。

      JDBC?API得到數(shù)據(jù)庫開發(fā)廠商,連接開發(fā)廠商,ISV,以及應(yīng)用開發(fā)者的支持是十分重要的。我們相信把我們的工作建立在ODBC抽象層的基礎(chǔ)上將JDBC更加容易得到大家的接受。而且從技術(shù)上來說,ODBC是我們設(shè)計工作的一個良好基礎(chǔ)。

      因為ODBC是一個C語言接口,所以O(shè)DBC在Java中直接使用不適當(dāng)。從Java中來調(diào)用C代碼在安全性,健壯性,實現(xiàn)的方便,可移植性等等方面有許多不便。它使得Java在這些方面的許多優(yōu)點得不到發(fā)揮。

      我們已經(jīng)在短期里面實現(xiàn)了一個建立在ODBC上的API。長遠來看,我們可以通過其他方式提供實現(xiàn)。

    1.?1.?注意

      我們非常感謝在數(shù)據(jù)庫,數(shù)據(jù)庫連接和數(shù)據(jù)庫工具領(lǐng)域的許多早期的工作者。他們?yōu)镴DBC的早期草案提供了很好的意見和建議。他們的工作對本規(guī)范起了不可估量的作用。?

     

    2.?目標與哲學(xué)

      這個部分描述了指引這個API開發(fā)的目標以及哲學(xué)。

    2.?1.?SQL?級?API

      我們的主要目標是為Java定義一個“調(diào)用級”(call-level)的SQL接口。著意味著我們主要的注意力集中在執(zhí)行原原本本的SQL語句并且取回結(jié)果。我們預(yù)計高層的API也將被定義,這些可能將建立在基層的接口上。

      這些高層接口包括象直接地、透明地把表里面的數(shù)據(jù)影射到Java類里面,用語法樹表示更加通用的查詢,以及Java內(nèi)嵌的SQL語法。

      我們希望大量的應(yīng)用開發(fā)工具將使用我們的API。然而我們也希望程序員能夠使用我們的API,尤其是目前這樣在Java里沒有任何其他手段(應(yīng)該是說數(shù)據(jù)庫訪問手段)的情況下。

    2.?2.?遵循SQL?

      數(shù)據(jù)庫系統(tǒng)支持各式各樣的SQL語法和語義,它們相互之間在比較高級的功能例如外部連接,內(nèi)嵌過程等方面并不一致,盡管我們能夠盼望著隨時間的推移這些部分的SQL可以獲得標準化。同時我們采取這樣的態(tài)度與立場:

      In?fact,?an?application?query?need?not?even?be?SQL,?or?it?may?be?a?specialized?derivative?of?SQL,?e.g.?for?document?or?image?queries,?designed?for?specific?DBMSs.?

      In?order?to?pass?JDBC?compliance?tests?and?to?be?called?"JDBC?COMPLIANT?"?we?require?that?a?driver?support?at?least?ANSI?SQL-2?Entry?Level.?This?gives?applications?that?want?wide?portability?a?guaranteed?least?common?denominator.?We?believe?ANSI?SQL-2?Entry?Level?is?reasonably?powerful?and?is?reasonably?widely?supported?today.

    *?JDBC允許查詢表達式直接傳遞到底層的數(shù)據(jù)驅(qū)動,這樣一個程序可以獲得盡量多的SQL功能,但是可能被DBMS拒絕。事實上,一個程序的查詢甚至可以不是SQL的,或者是SQL的一個特殊演化,例如:為專門數(shù)據(jù)庫設(shè)計的文本或者圖形查詢。

    *?為了通過JDBC兼容的測試,并且能夠被稱為JDBC兼容,我們要求一個驅(qū)動至少支持ANSI?SQL-2的標準。這使得那些需要廣泛移植性的程序獲得一個最小的分母(這句話的原文是:This?gives?applications?that?want?wide?portability?a?guaranteed?least?common?denominator.)。我們相信ANSI?SQL-2是足夠強大的,并且是得到足夠支持的。

    2.?3.?JDBC必須可以建立在現(xiàn)有的數(shù)據(jù)庫接口上

      我們必須能夠保證?JDBC?SQL?API?能夠建立在普通的SQL?API上,尤其是ODBC。這些要求已經(jīng)對這個規(guī)范的一些部分產(chǎn)生了影響,尤其是對傳出參數(shù)(OUT?parameter)和大數(shù)據(jù)塊的處理。

    2.?4.?必須保證這個接口與JAVA系統(tǒng)的其他部分保持一致?

     目前對JAVA的積極回應(yīng)已經(jīng)十分熱烈。很大程度上是由于這個語言標準以及標準運行時庫被認為是一致,簡單和強大的。我們將盡我們所能,提供這個Java數(shù)據(jù)庫接口,這個接口將建立在Java內(nèi)核現(xiàn)有的這種風(fēng)格,并且將進一步加強它。

    2.?5.?保持簡單

      We?would?prefer?to?keep?this?base?API?as?simple?as?possible,?at?least?initially.?In?general?we?would?prefer?to?provide?a?single?mechanism?for?performing?a?particular?task,?and?avoid?provid-ing?duplicate?mechanisms.?We?will?extend?the?API?later?if?any?important?functionality?is?miss-ing.

      我們將力爭使得基本的API盡量簡單,至少開始的時候是這樣的。一般來說,我們希望對實現(xiàn)每個特定的任務(wù)只提供一種方案,而避免提供多種方案。如果一些重要的功能遺漏了,那么我們在晚些時候?qū)U充這個API。

    2.?6.?盡量保持強的、靜態(tài)的類型

      我們希望這個JDBC?API保持盡量強的類型檢查,使得盡可能多的類型信息可以靜態(tài)地表達。著使得盡可能多的錯誤可以在編譯的時候被發(fā)現(xiàn)。

      由于SQL本身是動態(tài)類型的,所以我們可能會在程序運行的時候遇到類型不能匹配的問題。例如:當(dāng)一個程序員在希望SELECT返回一個整數(shù),但是實際返回的是一個字符串“foo”.?但是我們依然希望程序員把他們所希望的類型在編譯的時候就能夠表達清楚,這樣我們可以做盡可能多的靜態(tài)檢查。我們也希望在必要的時候能夠支持動態(tài)類型接口(見第四章)

    2.?7.?使普通任務(wù)簡化

      我們希望普通的任務(wù)能夠是簡單的,而不一般的工作是可行的。

      一個普通任務(wù)是指一個程序員執(zhí)行一個簡單的沒有參數(shù)的SQL語句(例如:SELECT,INSERT,UPDATE,DELETE),然后(例如SELECT)處理返回的具有簡單類型的元組。一個具有傳入?yún)?shù)(IN?parameter)的SQL語句也是普通的。

      不那么普通但是也是十分重要的情形是當(dāng)程序員使用有INOUT,OUT參數(shù)的SQL語句。我們也需要支持讀寫幾兆字節(jié)對象的SQL語句,更特別一些的情形包括一個語句返回了多個結(jié)果集合。

      我們希望元數(shù)據(jù)(Meatdata)的使用很少的,只是那些熟練的程序員以及開發(fā)工具才需要處理的問題。元數(shù)據(jù)存取函數(shù)以及動態(tài)類型數(shù)據(jù)存取函數(shù)在這個文檔末尾,一般的程序員可以不必關(guān)心這些章節(jié)。

    2.?8.?不同的功能讓不同的方法(函數(shù))來實現(xiàn)(“方法”的原文是:method,這樣翻譯是跟VB的)

      一種界面設(shè)計風(fēng)格是使用很少的過程,提供許多作為參數(shù)傳遞的控制標志,這樣它們可以用來影響很大一個范圍內(nèi)的各種行為。來表達不同的功能。這趨向與使用很多的方法,但是每個方法都比較同意理解。

      一般來說,Java內(nèi)核類使用不同的方法(method)。這個步驟的主要優(yōu)點是開始學(xué)習(xí)基本界面的程序員可以不必被那些與復(fù)雜功能相關(guān)的參數(shù)所困擾。我們力圖在JDBC接口上也采用相同的策略。一般來說采用不同的方法而不是采用不同的標志和多用途的方法。

    3.?接口概貌

      接口分為兩個層次,一個是面向程序開發(fā)人員的JDBC?API。另外一個是底層的JDBC?Driver?API。

    3.?1.?JDBC?API

      JDBC?API?被描述成為彝族抽象的Java接口,似的應(yīng)用程序遠可以對某個數(shù)據(jù)庫打開連接,執(zhí)行SQL語句并且處理結(jié)果。最重要的接口是:

    *?java.sql.DriverManager?處理驅(qū)動的調(diào)入并且對產(chǎn)生新的數(shù)據(jù)庫連接提供支持。

    *?java.sql.Connection?代表對特定數(shù)據(jù)庫的連接。

    *?java.sql.Statement? 代表一個特定的容器,來對一個特定的數(shù)據(jù)庫執(zhí)行SQL語句。

    *?java.sql.ResultSet? 控制對一個特定語句的行數(shù)據(jù)的存取。

    其中java.sql.Statement又有兩個子類型:

    1.?java.sql.PreparedStatement? 用于執(zhí)行預(yù)編譯的SQL語句。

    2.?java.sql.CallableStatement? 用于執(zhí)行對一個數(shù)據(jù)庫內(nèi)嵌過程的調(diào)用。

      下面的章節(jié)對JDBC是如何運行的提供了更多描述,整個定義見第13章。另外第15章描述了系統(tǒng)如果獲取數(shù)據(jù)庫的元數(shù)據(jù)信息。

    3.?2.?JDBC?Driver?API

      java.sql.Driver在第9章有完整的定義了.大部分JDBC驅(qū)動只需要完成這些JDBC?API所定義的抽象類就可以了。特別地,所有的driver必須提供對java.sql.Connection,?java.sql.?State-ment,?java.sql.Prepared-Statement,?and?java.sql.ResultSet的實現(xiàn)。如果目標DBMS提供有OUT參數(shù)的內(nèi)嵌過程,那么還必須提供java.sql.CallableStatement?接口。?每個database?driver必須提供一個類:java.sql.Driver以使得系統(tǒng)可以由?java.sql.DriverManager來管理。

      一個顯然的driver是在ODBC之上提供對JDBC的實現(xiàn),從而提供與ODBC接口的JDBC-ODBC?橋,就象前面的圖所顯示的.由于JDBC放在ODBC之后,所以實現(xiàn)起來簡單而且高效。

      另外一個有用的驅(qū)動直接接觸數(shù)據(jù)庫無關(guān)的網(wǎng)絡(luò)協(xié)議。發(fā)布一個協(xié)議允許多個服務(wù)器實現(xiàn)的方法,例如在ODBC或者特定的DBMS上(盡管已經(jīng)有了一些使用固定協(xié)議的產(chǎn)品,但是我們不打算對它們實現(xiàn)標準化。),是可取的。

     

    4.?JDBC使用場合

      Before?looking?at?specifics?of?the?JDBC?API,?an?understanding?of?typical?use?scenarios?is?help-ful.?There?are?two?common?scenarios?that?must?be?treated?differently?for?our?purposes:?applets?and?applications.

      在看JDBC?API之前了解一下典型的使用場合是有幫助的。通常有兩種情形必須分別對待:applet和application.

    4.?1.?Applet

      目前Java使用的最多的從網(wǎng)絡(luò)中下載的applet,它們作為web文件的一個部分。當(dāng)中有數(shù)據(jù)庫存取applet和能夠使用JDBC來接觸數(shù)據(jù)庫的applet。例如,一個用戶可能下載一個顯示股票歷史價格圖的applet。這個applet通過internet來從關(guān)系數(shù)據(jù)庫中獲得股票歷史價格。

      最一般的情況里面,對applet的使用是通過不可靠的邊界的。例如從另外一個公司或者Internet上獲得這些applet。于是稱這個情況為"Internet"場合。然而applet也可能通過局域網(wǎng)下載。在這個情況里面,客戶機的安全都還是一個問題。

    典型的applet在幾個方面與傳統(tǒng)的數(shù)據(jù)庫應(yīng)用程序有所不同:

    1).?不可靠的applet被嚴格地限制在他們被允許執(zhí)行的的操作上。特別地,不允許他們存取本地的文件,切不允許他們對任意的數(shù)據(jù)庫建立網(wǎng)絡(luò)連接。

    2).?就標識和連接網(wǎng)上數(shù)據(jù)庫來說,Internet環(huán)境里面的applet面臨新的問題。

    3).?當(dāng)數(shù)據(jù)庫可能與你相隔萬里的時候,效率的考慮也有所不同了。與局域網(wǎng)相比,Internet上數(shù)據(jù)庫applet可能會碰到十分不同的反應(yīng)時間。

    4.?2.?Application

      Java也可以用來建立普通的應(yīng)用,從而想一般的應(yīng)用一樣在客戶機上使用。我們相信隨著開發(fā)工具越來越多,人們開始認識到提高程序生產(chǎn)效率的必要性,以及Java的其他優(yōu)點,Java的這種用法將越來越流行。在這種方式里面,Java的代碼是可以信賴的,且被允許讀寫文件打開網(wǎng)絡(luò)連接等等,就想其他的應(yīng)用程序代碼一樣。

      也許這些Java應(yīng)用使用的最多的是在一個公司內(nèi)部或者在Intranet上,所以不妨成為Intranet場合。例如一個公司希望利用Java及其GUI構(gòu)件工具來建立他的基于合作數(shù)據(jù)模式的合作軟件。這些應(yīng)用程序?qū)⒋嫒【钟蚓W(wǎng)或者廣域網(wǎng)的數(shù)據(jù)。Java應(yīng)用可以作到這些。

      Java應(yīng)用程序場合和Intranet場合與applet場合有諸多不同。例如標定一個數(shù)據(jù)庫最自然的方式是用一個數(shù)據(jù)庫的名字,就象"Customers"?和"Personnel"這樣。然后用戶希望系統(tǒng)能夠定位具體的機器,DBMS,JDBC?driver,和Java應(yīng)用程序。

    4.?3.?其他場合

    還有其他一些有趣的場合:

    1).?已驗證的applet(Trusted?applets)是指那些已經(jīng)被Java虛擬機器認定是可以信賴的applet。他們之所以被認為是可信的是因為他們已經(jīng)對上了特定的密匙,或者用戶認為從特定來源來的applet是可信的。在安全的方面上他們與應(yīng)用(appliction)相同,但是其他方面(例如定位一個數(shù)據(jù)庫)與則與applet相似。

    2).?與直接從Java?GUI出發(fā)用客戶/服務(wù)器模式來度曲DBMS服務(wù)器不同,三層存取方式可能被使用。在這個場合里面,Java應(yīng)用程序?qū)χ虚g層的服務(wù)發(fā)出調(diào)用,中間層的服務(wù)在網(wǎng)上,它又再去調(diào)用數(shù)據(jù)庫。這些調(diào)用可能通過RPC?(remote?procedure?call)或者ORB?(object?request?broker?)。在這兩種場合里面,中間層最好使用一個對象變化。我們希望三層結(jié)構(gòu)會變得越來越普遍,因為對于MIS管理者來說,這可以使得他們有機會在公共數(shù)據(jù)庫上顯式地定義合法操作等。同時三層結(jié)構(gòu)可以提供許多效率上的好處。

      目前中間層一般用C或者C++這樣的語言來完成。通過優(yōu)化編譯器把把Java?字節(jié)代碼翻譯成為高效的機器代碼,中間層也可以用Java來實現(xiàn)。Java有許多優(yōu)良特性(健壯性,安全性,多線程)可以達到中間層需要達到的目的。?

     

    5.?安全性考慮

      作為網(wǎng)絡(luò)上的語言JAVA必須十分注安全性的考慮。基于上面的討論,JDBC的兩種主要使用場合里面,我們必須考慮安全性問題:

    *?在Java?applications的場合里面Java代碼是本地的,所以也是"trusted"?

    *?沒有驗證的Java?applet代碼不可以存取本地的以及其他網(wǎng)絡(luò)的數(shù)據(jù)。

    5.?1.?JDBC?和未驗證的applet

    JDBC首先必須符合JAVA的一般安全規(guī)則。另外:

    *?JDBC?必須認為沒有驗證的applets是不可靠的。

    *?JDBC?不可以讓不可靠的applets存取本地數(shù)據(jù)庫。

    *?一個已經(jīng)向JDBC?DriverManager注冊的是JDBC?Driver只能存取它所來的數(shù)據(jù)源。

    *?一個applet也只能向它所Download來的服務(wù)器來存取數(shù)據(jù)。

      如果JDBC驅(qū)動層如果完全確信對一個數(shù)據(jù)庫服務(wù)器打開連接不會引起認證或者權(quán)限問題(可能由網(wǎng)上隨機主機上運行的程序引起),那么它就允許applet打開這樣的連接。數(shù)據(jù)庫服務(wù)器不通過IP地址來限制存取是相當(dāng)少的,主要是為了舉例。(當(dāng)心,這一段話我可能翻譯反了!!!大家看看原文。)這些限制是相當(dāng)煩瑣的。不過他們與對一般applet的限制是一致的我們沒有必要放開這些限制。

    5.?2.?JDBC?和Java應(yīng)用程序

      對于一個普通的Java應(yīng)用程序(例如全部用Java代碼而不是不可靠的applet?)JDBC將從本地的類路徑里面獲得驅(qū)動,并且允許應(yīng)用程序自由存取文件,遠程服務(wù)器等等。

      但是和applet一樣,如果由于某些原因一個沒有驗證的sun.sql.Driver類從遠程的來源里面獲得,那么這個驅(qū)動只能和相同地方來的代碼配合。

    5.?3.?Driver的安全責(zé)任

      JDBC?driver可能在各種情況下使用,所以驅(qū)動的編制者遵循一定的簡單的安全規(guī)則,從而避免applet做非法的數(shù)據(jù)庫連接。

      如果所有的驅(qū)動都象applet一樣從網(wǎng)上下載,那么這些原則將是不必要的,因為普通的安全規(guī)則已經(jīng)對它做了限制。但是驅(qū)動的編寫者必須記住一旦他們的驅(qū)動獲得成功,用戶將在本地磁盤安裝這些驅(qū)動,那么驅(qū)動將成為Java環(huán)境中一個被信任的部分,所以必須確信它不會被來訪的applet所濫用。所以我們鼓勵所有的驅(qū)動編寫者必須遵循一定安全原則。

      所有這些原則都是在連接打開的時候使用。這正式驅(qū)動和虛擬機器檢查當(dāng)前調(diào)用者是否真的可以與指定的數(shù)據(jù)庫連接的時刻。一旦連接建立就不必做更多的檢查了。

    5.?3.?1.?分享TCP/IP連接的時候必須謹慎?  如果一個JDBC驅(qū)動試圖打開一個?TCP?連接,那么這個打開會被Java?安全管理機制自動檢查。這個機構(gòu)會檢查當(dāng)前調(diào)用棧里面有沒有applet,如果有那么就限定它可以訪問的機器集合。所以一般地JDBC驅(qū)動可以把TCP建立檢查留給Java虛擬機。

      但是如果一個JDBC驅(qū)動試圖在多個數(shù)據(jù)庫連接之間共享一個TCP連接,那么驅(qū)動就必須自己負責(zé)檢查每個調(diào)用者是否真的被允許與目標數(shù)據(jù)庫聯(lián)系。例如如果我們?yōu)閍pplet?A打開了一個通往機器foobah?的TCP連接,這并不意味著applet?B被自動允許來共享這個連接。applet?B可能沒有任何訪問機器foobah的權(quán)力。所以在允許某個程序重用一個現(xiàn)成的TCP連接之前,JDBC?驅(qū)動必須通過安全機構(gòu)來檢查當(dāng)前的的調(diào)用者是否可以訪問這個連接。通過下面的代碼可是實現(xiàn)這個功能。

    SecurityManager?security?=?System.getSecurityManager();?

    if?(security?!=?null)?

    {?

    security.checkConnect(hostName,?portNumber);?

    }

      如果連接是不允許的,那么Security.checkConnect方法將產(chǎn)生一個java.lang.SecurityException。?5.?3.?2.?檢查所有的本地文件訪問

      如果一個JDBC取得需要訪問本地機器上的數(shù)據(jù),那么他必須確信調(diào)用者是被允許打開這個文件的。例如:

    SecurityManager?security?=?System.getSecurityManager();?

    if?(security?!=?null)?

    {?

    security.checkRead(fileName);?

    }

      如果對特定文件的訪問是不允許的,那么Security.checkRead方法將產(chǎn)生一個java.lang.SecurityException。

    5.?3.?3.?作好最壞的準備

      一些驅(qū)動可能使用本地的方法來橋接底層數(shù)據(jù)庫程序。則這些情況里面判斷那些本地文件將被底層函數(shù)所訪問是困難的。

      在這些環(huán)境里面用戶必須作好最壞的打算,并且否決所有下載applet所發(fā)出的數(shù)據(jù)庫存取,除非驅(qū)動可能完全確信將要做存取是沒有問題的。

      例如一個JDBC-ODBC橋接器必須檢查ODBC數(shù)據(jù)源的的名稱,確保applet只可以訪問它的"生源地"。如果對有的名字中不能判斷出數(shù)據(jù)源的主機名,那么只能否決這個訪問。

      為了決定一個當(dāng)前的調(diào)用者是可以信賴的應(yīng)用還是一個applet,JDBC驅(qū)動必須能夠檢查這個調(diào)用者是否可以寫一個隨機的文件:

    SecurityManager?security?=?System.getSecurityManager();?

    if?(security?!=?null)?

    {?

    security.checkWrite("foobaz");?

    I.?}?
    posted on 2005-11-20 19:40 Cheng Ⅱ 閱讀(350) 評論(11) ?編輯?收藏

    評論

    #?JDBC基礎(chǔ)教程之概述 2005-11-20 19:42 Cheng Ⅱ
    1.1 什么是 JDBCTM?

      JDBCTM 是一種用于執(zhí)行 SQL 語句的 JavaTM API(有意思的是,JDBC 本身是個商標名而不是一個縮寫字;然而,JDBC常被認為是代表 “Java 數(shù)據(jù)庫連接 (Java Database Connectivity)”)。它由一組用 Java 編程語言編寫的類和接口組成。JDBC 為工具/數(shù)據(jù)庫開發(fā)人員提供了一個標準的 API,使他們能夠用純Java API 來編寫數(shù)據(jù)庫應(yīng)用程序。

      有了 JDBC,向各種關(guān)系數(shù)據(jù)庫發(fā)送 SQL 語句就是一件很容易的事。換言之,有了JDBC API,就不必為訪問 Sybase 數(shù)據(jù)庫專門寫一個程序,為訪問 Oracle 數(shù)據(jù)庫又專門寫一個程序,為訪問Informix 數(shù)據(jù)庫又寫另一個程序,等等。您只需用 JDBC API 寫一個程序就夠了,它可向相應(yīng)數(shù)據(jù)庫發(fā)送 SQL 語句。而且,使用 Java 編程語言編寫的應(yīng)用程序,就無須去憂慮要為不同的平臺編寫不同的應(yīng)用程序。將 Java 和 JDBC 結(jié)合起來將使程序員只須寫一遍程序就可讓它在任何平臺上運行。

      Java 具有堅固、安全、易于使用、易于理解和可從網(wǎng)絡(luò)上自動下載等特性,是編寫數(shù)據(jù)庫應(yīng)用程序的杰出語言。所需要的只是 Java 應(yīng)用程序與各種不同數(shù)據(jù)庫之間進行對話的方法。而 JDBC 正是作為此種用途的機制。

      JDBC 擴展了 Java 的功能。例如,用 Java 和 JDBC API 可以發(fā)布含有 applet的網(wǎng)頁,而該 applet 使用的信息可能來自遠程數(shù)據(jù)庫。企業(yè)也可以用 JDBC 通過Intranet 將所有職員連到一個或多個內(nèi)部數(shù)據(jù)庫中(即使這些職員所用的計算機有 Windows、 Macintosh 和 UNIX 等各種不同的操作系統(tǒng))。隨著越來越多的程序員開始使用 Java 編程語言,對從 Java中便捷地訪問數(shù)據(jù)庫的要求也在日益增加。

      MIS 管理員們都喜歡 Java 和 JDBC 的結(jié)合,因為它使信息傳播變得容易和經(jīng)濟。企業(yè)可繼續(xù)使用它們安裝好的數(shù)據(jù)庫,并能便捷地存取信息,即使這些信息是儲存在不同數(shù)據(jù)庫管理系統(tǒng)上。新程序的開發(fā)期很短。安裝和版本控制將大為簡化。程序員可只編寫一遍應(yīng)用程序或只更新一次,然后將它放到服務(wù)器上,隨后任何人就都可得到最新版本的應(yīng)用程序。對于商務(wù)上的銷售信息服務(wù), Java 和 JDBC 可為外部客戶提供獲取信息更新的更好方法。

      1.1.1 JDBC 的用途是什么?

      簡單地說,JDBC 可做三件事:

      與數(shù)據(jù)庫建立連接,
      發(fā)送 SQL 語句,
      處理結(jié)果。

      下列代碼段給出了以上三步的基本示例:

    Connection con = DriverManager.getConnection ("jdbc:odbc:wombat", "login", "password");
    Statement stmt = con.createStatement();
    ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
    while (rs.next())
    System.out.println(rs.getString("a") + " " + rs.getString("b") + " " + rs.getString("c"));

      1.1.2 JDBC 是一種低級 API ,是高級 API 的基礎(chǔ)

      JDBC 是個“低級”接口,也就是說,它用于直接調(diào)用 SQL 命令。在這方面它的功能極佳,并比其它的數(shù)據(jù)庫連接 API 易于使用,但它同時也被設(shè)計為一種基礎(chǔ)接口,在它之上可以建立高級接口和工具。

      高級接口是“對用戶友好的”接口,它使用的是一種更易理解和更為方便的 API,這種 API 在幕后被轉(zhuǎn)換為諸如 JDBC 這樣的低級接口。在編寫本文時,正在開發(fā)兩種基于 JDBC 的高級 API:

      一種用于 Java 的嵌入式 SQL。至少已經(jīng)有一個提供者計劃編寫它。DBMS 實現(xiàn)SQL:一種專門設(shè)計來與數(shù)據(jù)庫聯(lián)合使用的語言。JDBC 要求 SQL 語句必須作為 String 傳給 Java 方法。相反,嵌入式 SQL預(yù)處理器允許程序員將 SQL 語句直接與Java 混在一起使用。例如,可在 SQL 語句中使用 Java 變量,用以接受或提供SQL 值。然后,嵌入式 SQL 預(yù)處理器將通過 JDBC 調(diào)用把這種 Java/SQL 的混合物轉(zhuǎn)換為Java。關(guān)系數(shù)據(jù)庫表到 Java 類的直接映射。JavaSoft 和其它提供者都聲稱要實現(xiàn)該API。在這種“對象/關(guān)系”映射中,表中的每行對應(yīng)于類的一個實例,而每列的值對應(yīng)于該實例的一個屬性。于是,程序員可直接對 Java 對象進行操作;存取數(shù)據(jù)所需的 SQL 調(diào)用將在“掩蓋下”自動生成。此外還可提供更復(fù)雜的映射,例如將多個表中的行結(jié)合進一個 Java 類中。

      隨著人們對 JDBC 的興趣日益增漲,越來越多的開發(fā)人員一直在使用基于 JDBC 的工具,以使程序的編寫更加容易。程序員也一直在編寫力圖使最終用戶對數(shù)據(jù)庫的訪問變得更為簡單的應(yīng)用程序。例如,應(yīng)用程序可提供一個選擇數(shù)據(jù)庫任務(wù)的菜單。任務(wù)被選定后,應(yīng)用程序?qū)⒔o出提示及空白供填寫執(zhí)行選定任務(wù)所需的信息。所需信息輸入后,應(yīng)用程序?qū)⒆詣诱{(diào)用所需的SQL 命令。在這樣一種程序的協(xié)助下,即使用戶根本不懂 SQL 的語法,也可以執(zhí)行數(shù)據(jù)庫任務(wù)。


    #?JDBC基礎(chǔ)教程之連接 2005-11-20 19:44 Cheng Ⅱ
    Connection 對象代表與數(shù)據(jù)庫的連接。連接過程包括所執(zhí)行的 SQL 語句和在該連接上所返回的結(jié)果。一個應(yīng)用程序可與單個數(shù)據(jù)庫有一個或多個連接,或者可與許多數(shù)據(jù)庫有連接。2.1.1 打開連接與數(shù)據(jù)庫建立連接的標準方法是調(diào)用DriverManager.getConnection方法。該方法接受含有某個 URL 的字符串。DriverManager 類(即所謂的 JDBC管理層)將嘗試找到可與那個 URL 所代表的數(shù)據(jù)庫進行連接的驅(qū)動程序。DriverManager 類存有已注冊的 Driver 類的清單。當(dāng)調(diào)用方法 getConnection 時,它將檢查清單中的每個驅(qū)動程序,直到找到可與URL 中指定的數(shù)據(jù)庫進行連接的驅(qū)動程序為止。Driver 的方法connect 使用這個 URL來建立實際的連接。



      用戶可繞過 JDBC 管理層直接調(diào)用 Driver 方法。這在以下特殊情況下將很有用:當(dāng)兩個驅(qū)動器可同時連接到數(shù)據(jù)庫中,而用戶需要明確地選用其中特定的驅(qū)動器。但一般情況下,讓 DriverManager 類處理打開連接這種事將更為簡單。

      下述代碼顯示如何打開一個與位于 URL "jdbc:odbc:wombat" 的數(shù)據(jù)庫的連接。所用的用戶標識符為 "oboy" ,口令為 "12Java":

    String url = "jdbc:odbc:wombat";
    Connection con = DriverManager.getConnection(url, "oboy", "12Java");

      2.1.2 一般用法的 URL由于 URL 常引起混淆,我們將先對一般 URL 作簡單說明,然后再討論 JDBC URL。

      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

      2.1.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é)議 >:< 子名稱 >

      JDBC URL 的三個部分可分解如下: jdbc ─ 協(xié)議。

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

      <子協(xié)議> ─ 驅(qū)動程序名或數(shù)據(jù)庫連接機制(這種機制可由一個或多個驅(qū)動程序支持)的名稱。子協(xié)議名的典型示例是 "odbc",該名稱是為用于指定 ODBC 風(fēng)格的數(shù)據(jù)資源名稱的 URL 專門保留的。例如,為了通過JDBC-ODBC 橋來訪問某個數(shù)據(jù)庫,可以用如下所示的 URL:

    jdbc:odbc:fred

      本例中,子協(xié)議為 "odbc",子名稱 "fred" 是本地ODBC 數(shù)據(jù)資源。

      如果要用網(wǎng)絡(luò)命名服務(wù)(這樣 JDBC URL 中的數(shù)據(jù)庫名稱不必是實際名稱),則命名服務(wù)可以作為子協(xié)議。例如,可用如下所示的 URL :jdbc:dcenaming:accounts-payable本例中,該 URL 指定了本地 DCE 命名服務(wù)應(yīng)該將數(shù)據(jù)庫名稱 "accounts-payable" 解析為更為具體的可用于連接真實數(shù)據(jù)庫的名稱。<子名稱> ─ 一種標識數(shù)據(jù)庫的方法。子名稱可以依不同的子協(xié)議而變化。它還可以有子名稱的子名稱(含有驅(qū)動程序編程員所選的任何內(nèi)部語法)。使用子名稱的目的是為定位數(shù)據(jù)庫提供足夠的信息。前例中,因為 ODBC 將提供其余部份的信息,因此用 "fred" 就已足夠。然而,位于遠程服務(wù)器上的數(shù)據(jù)庫需要更多的信息。例如,如果數(shù)據(jù)庫是通過Internet 來訪問的,則在 JDBC URL 中應(yīng)將網(wǎng)絡(luò)地址作為子名稱的一部份包括進去,且必須遵循如下所示的標準 URL 命名約定://主機名:端口/子協(xié)議假設(shè) "dbnet" 是個用于將某個主機連接到 Internet 上的協(xié)議,則 JDBC URL 類似:

      jdbc:dbnet://wombat:356/fred 2.1.4 "odbc" 子協(xié)議子協(xié)議 odbc 是一種特殊情況。它是為用于指定 ODBC 風(fēng)格的數(shù)據(jù)資源名稱的 URL 而保留的,并具有下列特性:允許在子名稱(數(shù)據(jù)資源名稱)后面指定任意多個屬性值。odbc 子協(xié)議的完整語法為: jdbc:odbc:< 數(shù)據(jù)資源名稱 >[;< 屬性名 >=< 屬性值 >]*

      因此,以下都是合法的 jdbc:odbc 名稱:

    jdbc:odbc:qeor7jdbc:odbc:wombat
    jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER
    jdbc:odbc:qeora;UID=kgh;PWD=fooey



    #?JDBC基礎(chǔ)教程之PreparedStatement 2005-11-20 19:44 Cheng Ⅱ
    概述

      該 PreparedStatement 接口繼承 Statement,并與之在兩方面有所不同:

      PreparedStatement 實例包含已編譯的 SQL 語句。這就是使語句“準備好”。包含于 PreparedStatement 對象中的 SQL 語句可具有一個或多個 IN 參數(shù)。IN參數(shù)的值在 SQL 語句創(chuàng)建時未被指定。相反的,該語句為每個 IN 參數(shù)保留一個問號(“?”)作為占位符。每個問號的值必須在該語句執(zhí)行之前,通過適當(dāng)?shù)膕etXXX 方法來提供。



      由于 PreparedStatement 對象已預(yù)編譯過,所以其執(zhí)行速度要快于 Statement 對象。因此,多次執(zhí)行的 SQL 語句經(jīng)常創(chuàng)建為 PreparedStatement 對象,以提高效率。

      作為 Statement 的子類,PreparedStatement 繼承了 Statement 的所有功能。另外它還添加了一整套方法,用于設(shè)置發(fā)送給數(shù)據(jù)庫以取代 IN 參數(shù)占位符的值。同時,三種方法 execute、 executeQuery 和 executeUpdate 已被更改以使之不再需要參數(shù)。這些方法的 Statement 形式(接受 SQL 語句參數(shù)的形式)不應(yīng)該用于 PreparedStatement 對象。

      1、創(chuàng)建 PreparedStatement 對象

      以下的代碼段(其中 con 是 Connection 對象)創(chuàng)建包含帶兩個 IN 參數(shù)占位符的 SQL 語句的 PreparedStatement 對象:

    PreparedStatement pstmt = con.prepareStatement("UPDATE table4 SET m = ? WHERE x = ?");

      pstmt 對象包含語句 "UPDATE table4 SET m = ? WHERE x = ?",它已發(fā)送給DBMS,并為執(zhí)行作好了準備。

      2、傳遞 IN 參數(shù)

      在執(zhí)行 PreparedStatement 對象之前,必須設(shè)置每個 ? 參數(shù)的值。這可通過調(diào)用 setXXX 方法來完成,其中 XXX 是與該參數(shù)相應(yīng)的類型。例如,如果參數(shù)具有Java 類型 long,則使用的方法就是 setLong。setXXX 方法的第一個參數(shù)是要設(shè)置的參數(shù)的序數(shù)位置,第二個參數(shù)是設(shè)置給該參數(shù)的值。例如,以下代碼將第一個參數(shù)設(shè)為 123456789,第二個參數(shù)設(shè)為 100000000:

    pstmt.setLong(1, 123456789);
    pstmt.setLong(2, 100000000);

      一旦設(shè)置了給定語句的參數(shù)值,就可用它多次執(zhí)行該語句,直到調(diào)用clearParameters 方法清除它為止。在連接的缺省模式下(啟用自動提交),當(dāng)語句完成時將自動提交或還原該語句。

      如果基本數(shù)據(jù)庫和驅(qū)動程序在語句提交之后仍保持這些語句的打開狀態(tài),則同一個 PreparedStatement 可執(zhí)行多次。如果這一點不成立,那么試圖通過使用PreparedStatement 對象代替 Statement 對象來提高性能是沒有意義的。

      利用 pstmt(前面創(chuàng)建的 PreparedStatement 對象),以下代碼例示了如何設(shè)置兩個參數(shù)占位符的值并執(zhí)行 pstmt 10 次。如上所述,為做到這一點,數(shù)據(jù)庫不能關(guān)閉 pstmt。在該示例中,第一個參數(shù)被設(shè)置為 "Hi"并保持為常數(shù)。在 for 循環(huán)中,每次都將第二個參數(shù)設(shè)置為不同的值:從 0 開始,到 9 結(jié)束。

    pstmt.setString(1, "Hi");
    for (int i = 0; i < 10; i++) {
     pstmt.setInt(2, i);
     int rowCount = pstmt.executeUpdate();
    }

      3、IN 參數(shù)中數(shù)據(jù)類型的一致性

      setXXX 方法中的 XXX 是 Java 類型。它是一種隱含的 JDBC 類型(一般 SQL 類型),因為驅(qū)動程序?qū)?Java 類型映射為相應(yīng)的 JDBC 類型(遵循該 JDBCGuide中§8.6.2 “映射 Java 和 JDBC 類型”表中所指定的映射),并將該 JDBC 類型發(fā)送給數(shù)據(jù)庫。例如,以下代碼段將 PreparedStatement 對象 pstmt 的第二個參數(shù)設(shè)置為 44,Java 類型為 short:

    pstmt.setShort(2, 44);

      驅(qū)動程序?qū)?44 作為 JDBC SMALLINT 發(fā)送給數(shù)據(jù)庫,它是 Java short 類型的標準映射。

      程序員的責(zé)任是確保將每個 IN 參數(shù)的 Java 類型映射為與數(shù)據(jù)庫所需的 JDBC 數(shù)據(jù)類型兼容的 JDBC 類型。不妨考慮數(shù)據(jù)庫需要 JDBC SMALLINT 的情況。如果使用方法 setByte ,則驅(qū)動程序?qū)?JDBC TINYINT 發(fā)送給數(shù)據(jù)庫。這是可行的,因為許多數(shù)據(jù)庫可從一種相關(guān)的類型轉(zhuǎn)換為另一種類型,并且通常 TINYINT 可用于SMALLINT 適用的任何地方

    #?JDBC基礎(chǔ)教程之ResultSet對象 2005-11-20 19:45 Cheng Ⅱ
    概述

      ResultSet 包含符合 SQL 語句中條件的所有行,并且它通過一套 get 方法(這些 get 方法可以訪問當(dāng)前行中的不同列)提供了對這些行中數(shù)據(jù)的訪問。ResultSet.next 方法用于移動到 ResultSet 中的下一行,使下一行成為當(dāng)前行。





      結(jié)果集一般是一個表,其中有查詢所返回的列標題及相應(yīng)的值。例如,如果查詢?yōu)?SELECT a, b, c FROM Table1,則結(jié)果集將具有如下形式:

    a b c
    -------- --------- --------
    12345 Cupertino CA
    83472 Redmond WA
    83492 Boston MA

      下面的代碼段是執(zhí)行 SQL 語句的示例。該 SQL 語句將返回行集合,其中列 1 為 int,列 2 為 String,而列 3 則為字節(jié)數(shù)組:

    java.sql.Statement stmt = conn.createStatement();
    ResultSet r = stmt.executeQuery("SELECT a, b, c FROM Table1");
    while (r.next())
    {
     // 打印當(dāng)前行的值。
     int i = r.getInt("a");
     String s = r.getString("b");
     float f = r.getFloat("c");
     System.out.println("ROW = " + i + " " + s + " " + f);
    }

      1、行和光標

      ResultSet 維護指向其當(dāng)前數(shù)據(jù)行的光標。每調(diào)用一次 next 方法,光標向下移動一行。最初它位于第一行之前,因此第一次調(diào)用 next 將把光標置于第一行上,使它成為當(dāng)前行。隨著每次調(diào)用 next 導(dǎo)致光標向下移動一行,按照從上至下的次序獲取ResultSet 行。

      在 ResultSet 對象或其父輩 Statement 對象關(guān)閉之前,光標一直保持有效。

      在 SQL 中,結(jié)果表的光標是有名字的。如果數(shù)據(jù)庫允許定位更新或定位刪除,則需要將光標的名字作為參數(shù)提供給更新或刪除命令。可通過調(diào)用方法getCursorName 獲得光標名。

      注意:不是所有的 DBMS 都支持定位更新和刪除。可使用 DatabaseMetaData.supportsPositionedDelete 和 supportsPositionedUpdate 方法來檢查特定連接是否支持這些操作。當(dāng)支持這些操作時,DBMS/驅(qū)動程序必須確保適當(dāng)鎖定選定行,以使定位更新不會導(dǎo)致更新異常或其它并發(fā)問題。



    #?JDBC基礎(chǔ)教程之CallableStatement 2005-11-20 19:47 Cheng Ⅱ
    概述

      CallableStatement 對象為所有的 DBMS 提供了一種以標準形式調(diào)用已儲存過程的方法。已儲存過程儲存在數(shù)據(jù)庫中。對已儲存過程的調(diào)用是 CallableStatement對象所含的內(nèi)容。這種調(diào)用是用一種換碼語法來寫的,有兩種形式:一種形式帶結(jié)果參,另一種形式不帶結(jié)果參數(shù)。結(jié)果參數(shù)是一種輸出 (OUT) 參數(shù),是已儲存過程的返回值。兩種形式都可帶有數(shù)量可變的輸入(IN 參數(shù))、輸出(OUT 參數(shù))或輸入和輸出(INOUT 參數(shù))的參數(shù)。問號將用作參數(shù)的占位符。





      在 JDBC 中調(diào)用已儲存過程的語法如下所示。注意,方括號表示其間的內(nèi)容是可選項;方括號本身并不是語法的組成部份。

    {call 過程名[(?, ?, ...)]}

      返回結(jié)果參數(shù)的過程的語法為:

    {? = call 過程名[(?, ?, ...)]}

      不帶參數(shù)的已儲存過程的語法類似:

    {call 過程名}

      通常,創(chuàng)建 CallableStatement 對象的人應(yīng)當(dāng)知道所用的 DBMS 是支持已儲存過程的,并且知道這些過程都是些什么。然而,如果需要檢查,多種DatabaseMetaData 方法都可以提供這樣的信息。例如,如果 DBMS 支持已儲存過程的調(diào)用,則supportsStoredProcedures 方法將返回 true,而getProcedures 方法將返回對已儲存過程的描述。CallableStatement 繼承 Statement 的方法(它們用于處理一般的 SQL 語句),還繼承了 PreparedStatement 的方法(它們用于處理 IN 參)。

      CallableStatement 中定義的所有方法都用于處理 OUT 參數(shù)或 INOUT 參數(shù)的輸出部分:注冊 OUT 參數(shù)的 JDBC 類型(一般 SQL 類型)、從這些參數(shù)中檢索結(jié)果,或者檢查所返回的值是否為 JDBC NULL。

      1、創(chuàng)建 CallableStatement 對象

      CallableStatement 對象是用 Connection 方法 prepareCall 創(chuàng)建的。下例創(chuàng)建 CallableStatement 的實例,其中含有對已儲存過程 getTestData 調(diào)用。該過程有兩個變量,但不含結(jié)果參數(shù):

    CallableStatement cstmt = con.prepareCall("{call getTestData(?, ?)}");

      其中?占位符為IN、OUT還是INOUT參數(shù),取決于已儲存過程getTestData。

      2、IN和OUT參數(shù)

      將IN參數(shù)傳給 CallableStatement 對象是通過 setXXX 方法完成的。該方法繼承自 PreparedStatement。所傳入?yún)?shù)的類型決定了所用的setXXX方法(例如,用 setFloat 來傳入 float 值等)。

      如果已儲存過程返回 OUT 參數(shù),則在執(zhí)行 CallableStatement 對象以前必須先注冊每個 OUT 參數(shù)的 JDBC 類型(這是必需的,因為某些 DBMS 要求 JDBC 類型)。注冊 JDBC 類型是用 registerOutParameter 方法來完成的。語句執(zhí)行完后,CallableStatement 的 getXXX 方法將取回參數(shù)值。正確的 getXXX 方法是為各參數(shù)所注冊的 JDBC 類型所對應(yīng)的 Java 類型。換言之, registerOutParameter 使用的是 JDBC 類型(因此它與數(shù)據(jù)庫返回的 JDBC 類型匹配),而 getXXX 將之轉(zhuǎn)換為 Java 類型。

      作為示例,下述代碼先注冊 OUT 參數(shù),執(zhí)行由 cstmt 所調(diào)用的已儲存過程,然后檢索在 OUT 參數(shù)中返回的值。方法 getByte 從第一個 OUT 參數(shù)中取出一個 Java 字節(jié),而 getBigDecimal 從第二個 OUT 參數(shù)中取出一個 BigDecimal 對象(小數(shù)點后面帶三位數(shù)):

    CallableStatement cstmt = con.prepareCall("{call getTestData(?, ?)}");
    cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
    cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 3);
    cstmt.executeQuery();
    byte x = cstmt.getByte(1);
    java.math.BigDecimal n = cstmt.getBigDecimal(2, 3);

      CallableStatement 與 ResultSet 不同,它不提供用增量方式檢索大 OUT 值的特殊機制。


    #?JDBC基礎(chǔ)教程之語句 2005-11-20 19:48 Cheng Ⅱ
    概述

      Statement 對象用于將 SQL 語句發(fā)送到數(shù)據(jù)庫中。實際上有三種 Statement 對象,它們都作為在給定連接上執(zhí)行 SQL 語句的包容器:Statement、PreparedStatement(它從 Statement 繼承而來)和 CallableStatement(它從 PreparedStatement 繼承而來)。它們都專用于發(fā)送特定類型的 SQL 語句: Statement 對象用于執(zhí)行不帶參數(shù)的簡單 SQL 語句;PreparedStatement 對象用于執(zhí)行帶或不帶 IN 參數(shù)的預(yù)編譯 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 的返回值總為零。

      方法 execute 用于執(zhí)行返回多個結(jié)果集、多個更新計數(shù)或二者組合的語句。因為多數(shù)程序員不會需要該高級功能,所以本概述后面將在單獨一節(jié)中對其進行介紹。

      執(zhí)行語句的所有方法都將關(guān)閉所調(diào)用的 Statement 對象的當(dāng)前打開結(jié)果集(如果存在)。這意味著在重新執(zhí)行 Statement 對象之前,需要完成對當(dāng)前 ResultSet 對象的處理。

      應(yīng)注意,繼承了 Statement 接口中所有方法的 PreparedStatement 接口都有自己的 executeQuery、executeUpdate 和 execute 方法。Statement 對象本身不包含 SQL 語句,因而必須給 Statement.execute 方法提供 SQL 語句作為參數(shù)。PreparedStatement 對象并不將 SQL 語句作為參數(shù)提供給這些方法,因為它們已經(jīng)包含預(yù)編譯 SQL 語句。CallableStatement 對象繼承這些方法的 PreparedStatement 形式。對于這些方法的 PreparedStatement 或 CallableStatement 版本,使用查詢參數(shù)將拋出 SQLException。

      3、語句完成

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

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

      4、關(guān)閉 Statement 對象

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



    #?JDBC基礎(chǔ)教程之驅(qū)動設(shè)置 2005-11-20 19:49 Cheng Ⅱ
    1、概述

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



      對于簡單的應(yīng)用程序,一般程序員需要在此類中直接使用的唯一方法是 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 中注冊的方式有兩種:

      通過調(diào)用方法 Class.forName。這將顯式地加載驅(qū)動程序類。由于這與外部設(shè)置無關(guān),因此推薦使用這種加載驅(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ū)動程序的第二種方法需要持久的預(yù)設(shè)環(huán)境。如果對這一點不能保證,則調(diào)用方法 Class.forName 顯式地加載每個驅(qū)動程序就顯得更為安全。這也是引入特定驅(qū)動程序的方法,因為一旦 DriverManager 類被初始化,它將不再檢查 jdbc.drivers 屬性列表。

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

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

      2、建立連接

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

      有時可能有多個 JDBC 驅(qū)動程序可以與給定的 URL 連接。例如,與給定遠程數(shù)據(jù)庫連接時,可以使用 JDBC-ODBC 橋驅(qū)動程序、JDBC 到通用網(wǎng)絡(luò)協(xié)議驅(qū)動程序或數(shù)據(jù)庫廠商提供的驅(qū)動程序。在這種情況下,測試驅(qū)動程序的順序至關(guān)重要,因為 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常用類和方法 2005-11-20 19:50 Cheng Ⅱ
    一、四種驅(qū)動程序概念

    A、JDBC-ODBC Bridge
    橋接器型的驅(qū)動程序,這類驅(qū)動程序的特色是必須在使用者端的計算機上事先安裝好ODBC驅(qū)動程序,然后通過JDBC-ODBC的調(diào)用方法,進而通過ODBC來存取數(shù)據(jù)庫。
    作為JDK1.1后的一部分,是sun.jdbc.odbc包的一部分
    Application--->JDBC-ODBC Bridge---->JDBC-ODBC Library--->ODBC Driver-->Database
    適用于快速的原型系統(tǒng),沒有提供JDBC驅(qū)動的數(shù)據(jù)庫如Access

    B、JDBC-Native API Bridge
    也是橋接器驅(qū)動程序之一,這類驅(qū)動程序也必須先在使用者計算機上先安裝好特定的驅(qū)動程序(類似ODBC),然后通過JDBC-Native API橋接器的轉(zhuǎn)換,把Java API調(diào)用轉(zhuǎn)換成特定驅(qū)動程序的調(diào)用方法,進而存取數(shù)據(jù)庫。
    利用開發(fā)商提供的本地庫來直接與數(shù)據(jù)庫通信。
    Application--->JDBC Driver---->Native Database library---->Database
    比A類性能略好。

    C、JDBC-middleware
    這類型的驅(qū)動程序最大的好處就是省去了在使用者計算機上安裝任何驅(qū)動程序的麻煩,只需在服務(wù)器端安裝好middleware,而middleware會負責(zé)所有存取數(shù)據(jù)庫必要的轉(zhuǎn)換。
    Application--->Jdbc Driver----->java middleware--->JDBC Driver---->Database
    具有最大的靈活性,通常由那些非數(shù)據(jù)庫廠商提供,是四種類型中最小的。

    D、Pure JDBC driver
    這類型的驅(qū)動程序是最成熟的JDBC驅(qū)動程序,不但無需在使用者計算機上安裝任何額外的驅(qū)動程序,也不需要在服務(wù)器端安裝任何中介程序(middleware),所有存取數(shù)據(jù)庫的操作,都直接由驅(qū)動程序來完成。
    Application--->Jdbc driver----->database engine--->database
    最高的性能,通過自己的本地協(xié)議直接與數(shù)據(jù)庫引擎通信,具備在Internet裝配的能力。


    二、常用的JDBC類與方法

    1、DriverManager類:
    負責(zé)管理JDBC驅(qū)動程序。使用JDBC驅(qū)動程序之前,必須先將驅(qū)動程序加載并向DriverManager注冊后才可以使用,同時提供方法來建立與數(shù)據(jù)庫的連接。

    方法:
    A、Class.forName(String driver); //加載注冊驅(qū)動程序
    B、Static Connection getConnection(String url,String user,String password) throws SQLException;
    //取得對數(shù)據(jù)庫的連接
    C、Static Driver getDriver(String url) throws SQLExcetion;
    //在已經(jīng)向DriverManager注冊的驅(qū)動程序中尋找一個能夠打開url所指定的數(shù)據(jù)庫的驅(qū)動程序


    2、Connection類
    負責(zé)維護JSP/JAVA數(shù)據(jù)庫程序和數(shù)據(jù)庫之間的聯(lián)機。可以建立三個非常有用的類對象。

    方法:
    A、Statement createStatement() throws SQLException; //建立Statement類對象
    Statement createStatement(int resultSetType,int resultSetConcurrency) throws SQLException;
    // 建立Statement類對象

    resultSetType值
    TYPE_FORWARD_ONLY 結(jié)果集不可滾動
    TYPE_SCROLL_INSENSITIVE 結(jié)果集可滾動,不反映數(shù)據(jù)庫的變化
    TYPE_SCROLL_SENSITIVE 結(jié)果集可滾動,反映數(shù)據(jù)庫的變化

    resultSetConcurrency值
    CONCUR_READ_ONLY 不能用結(jié)果集更新數(shù)據(jù)
    CONCUR_UPDATABLE 能用結(jié)果集更新數(shù)據(jù)

    JDBC2.0中才支持滾動的結(jié)果集,而且可以對數(shù)據(jù)進行更新

    B、DatabaseMetaData getMetaData() throws SQLException; //建立DatabaseMetaData類對象
    C、PreparedStatement prepareStatement(String sql) throws SQLException;
    //建立PreparedStatement類對象
    D、boolean getAutoCommit() throws SQLException //返回Connection類對象的AutoCommit狀態(tài)
    E、void setAutoCommit(boolean autoCommit) throws SQLException
    //設(shè)定Connection類對象的AutoCommit狀態(tài)
    F、void commit() throws SQLException //確定執(zhí)行對數(shù)據(jù)庫新增、刪除或修改記錄的操作
    G、void rollback() throws SQLException //取消執(zhí)行對數(shù)據(jù)庫新增、刪除或修改記錄的操作
    H、void close() throws SQLException //結(jié)束Connection對象對數(shù)據(jù)庫的聯(lián)機
    I、boolean isClosed() throws SQLException //測試是否已經(jīng)關(guān)閉Connection類對象對數(shù)據(jù)庫的聯(lián)機

    3、Statement類

    通過Statement類所提供的方法,可以利用標準的SQL命令,對數(shù)據(jù)庫直接新增、刪除或修改操作

    方法:

    A、ResultSet executeQuery(String sql) throws SQLException //使用SELECT命令對數(shù)據(jù)庫進行查詢
    B、int executeUpdate(String sql) throws SQLException
    //使用INSERT\DELETE\UPDATE對數(shù)據(jù)庫進行新增、刪除和修改操作。
    C、void close() throws SQLException //結(jié)束Statement類對象對數(shù)據(jù)庫的聯(lián)機


    4、PreparedStatement類

    PreparedStatement類和Statement類的不同之處在于PreparedStatement類對象會將傳入的SQL命令事先編好等待使用,當(dāng)有單一的SQL指令比多次執(zhí)行時,用PreparedStatement類會比Statement類有效率

    方法:

    A、ResultSet executeQuery() throws SQLException //使用SELECT命令對數(shù)據(jù)庫進行查詢
    B、int executeUpdate() throws SQLException
    //使用INSERT\DELETE\UPDATE對數(shù)據(jù)庫進行新增、刪除和修改操作。
    C、ResultSetMetaData getMetaData() throws SQLException
    //取得ResultSet類對象有關(guān)字段的相關(guān)信息
    D、void setInt(int parameterIndex,int x) throws SQLException
    //設(shè)定整數(shù)類型數(shù)值給PreparedStatement類對象的IN參數(shù)
    E、void setFloat(int parameterIndex,float x) throws SQLException
    //設(shè)定浮點數(shù)類型數(shù)值給PreparedStatement類對象的IN參數(shù)
    F、void setNull(int parameterIndex,int sqlType) throws SQLException
    //設(shè)定NULL類型數(shù)值給PreparedStatement類對象的IN參數(shù)
    G、void setString(int parameterIndex,String x) throws SQLException
    //設(shè)定字符串類型數(shù)值給PreparedStatement類對象的IN參數(shù)
    H、void setDate(int parameterIndex,Date x) throws SQLException
    //設(shè)定日期類型數(shù)值給PreparedStatement類對象的IN參數(shù)
    I、void setTime(int parameterIndex,Time x) throws SQLException
    //設(shè)定時間類型數(shù)值給PreparedStatement類對象的IN參數(shù)


    5、DatabaseMetaData類

    DatabaseMetaData類保存了數(shù)據(jù)庫的所有特性,并且提供許多方法來取得這些信息。

    方法:

    A、String getDatabaseProductName() throws SQLException //取得數(shù)據(jù)庫名稱
    B、String getDatabaseProductVersion() throws SQLException //取得數(shù)據(jù)庫版本代號
    C、String getDriverName() throws SQLException //取得JDBC驅(qū)動程序的名稱
    D、String getDriverVersion() throws SQLException //取得JDBC驅(qū)動程序的版本代號
    E、String getURL() throws SQLException //取得連接數(shù)據(jù)庫的JDBC URL
    F、String getUserName() throws SQLException //取得登錄數(shù)據(jù)庫的使用者帳號

    6、ResultSet類

    負責(zé)存儲查詢數(shù)據(jù)庫的結(jié)果。并提供一系列的方法對數(shù)據(jù)庫進行新增、刪除和修改操作。也負責(zé)維護一個記錄指針(Cursor),記錄指針指向數(shù)據(jù)表中的某個記錄,通過適當(dāng)?shù)囊苿佑涗浿羔槪梢噪S心所欲的存取數(shù)據(jù)庫,加強程序的效率。

    方法:

    A、boolean absolute(int row) throws SQLException //移動記錄指針到指定的記錄
    B、void beforeFirst() throws SQLException //移動記錄指針到第一筆記錄之前
    C、void afterLast() throws SQLException //移動記錄指針到最后一筆記錄之后
    D、boolean first() throws SQLException //移動記錄指針到第一筆記錄
    E、boolean last() throws SQLException //移動記錄指針到最后一筆記錄
    F、boolean next() throws SQLException //移動記錄指針到下一筆記錄
    G、boolean previous() throws SQLException //移動記錄指針到上一筆記錄
    H、void deleteRow() throws SQLException //刪除記錄指針指向的記錄
    I、void moveToInsertRow() throws SQLException //移動記錄指針以新增一筆記錄
    J、void moveToCurrentRow() throws SQLException //移動記錄指針到被記憶的記錄
    K、void insertRow() throws SQLException //新增一筆記錄到數(shù)據(jù)庫中
    L、void updateRow() throws SQLException //修改數(shù)據(jù)庫中的一筆記錄
    M、void update類型(int columnIndex,類型 x) throws SQLException //修改指定字段的值
    N、int get類型(int columnIndex) throws SQLException //取得指定字段的值
    O、ResultSetMetaData getMetaData() throws SQLException //取得ResultSetMetaData類對象

    7、ResultSetMetaData類

    ResultSetMetaData類對象保存了所有ResultSet類對象中關(guān)于字段的信息,提供許多方法來取得這些信息。

    方法:

    A、int getColumnCount() throws SQLException //取得ResultSet類對象的字段個數(shù)
    B、int getColumnDisplaySize() throws SQLException //取得ResultSet類對象的字段長度
    C、String getColumnName(int column) throws SQLException //取得ResultSet類對象的字段名稱
    D、String getColumnTypeName(int column) throws SQLException //取得ResultSet類對象的字段類型名稱
    E、String getTableName(int column) throws SQLException //取得ResultSet類對象的字段所屬數(shù)據(jù)表的名稱
    F、boolean isCaseSensitive(int column) throws SQLException //測試ResultSet類對象的字段是否區(qū)分大小寫
    G、boolean isReadOnly(int column) throws SQLException //測試ResultSet類對象的字段是否為只讀


    作者Blog:http://blog.csdn.net/chensheng913/


    #?常用數(shù)據(jù)庫JDBC連接寫法(轉(zhuǎn)摘) 2005-11-20 19:51 Cheng Ⅱ
    1. MySQL(http://www.mysql.com)mysql-connector-java-2.0.14-bin.jar


    Class.forName( "org.gjt.mm.mysql.Driver" ); cn = DriverManager.getConnection( "jdbc:mysql://MyDbComputerNameOrIP:3306/myDatabaseName", sUsr, sPwd );

    2. PostgreSQL(http://www.de.postgresql.org)pgjdbc2.jar


    Class.forName( "org.postgresql.Driver" ); cn = DriverManager.getConnection( "jdbc:postgresql://MyDbComputerNameOrIP/myDatabaseName", sUsr, sPwd );

    3.
    Oracle(http://www.oracle.com/ip/deploy/database/oracle9i/)classes12.zip


    Class.forName( "oracle.jdbc.driver.OracleDriver" ); cn = DriverManager.getConnection( "jdbc:oracle:thin:@MyDbComputerNameOrIP:1521:ORCL", sUsr, sPwd );

    4. Sybase(http://jtds.sourceforge.net">http://jtds.sourceforge.net
    )jconn2.jar

    Class.forName( "com.sybase.jdbc2.jdbc.SybDriver" ); cn = DriverManager.getConnection( "jdbc:sybase:Tds:MyDbComputerNameOrIP:2638", sUsr, sPwd ); //(Default-Username/Password: "dba"/"sql")

    5. Microsoft SQLServer(http://jtds.sourceforge.net">http://jtds.sourceforge.net)

    Class.forName( "net.sourceforge.jtds.jdbc.Driver" ); cn = DriverManager.getConnection( "jdbc:jtds:sqlserver://MyDbComputerNameOrIP:1433/master", sUsr, sPwd );
    6. Microsoft SQLServer(http://www.microsoft.com)

    Class.forName( "com.microsoft.jdbc.sqlserver.SQLServerDriver" ); cn = DriverManager.getConnection( "jdbc:microsoft:sqlserver://MyDbComputerNameOrIP:1433;databaseName=master", sUsr, sPwd );

    7. ODBC

    Class.forName( "sun.jdbc.odbc.JdbcOdbcDriver" ); Connection cn = DriverManager.getConnection( "jdbc:odbc:" + sDsn, sUsr, sPwd );

    8.DB2

    Class.forName("com.ibm.db2.jdbc.net.DB2Driver"); String url="jdbc:db2://192.9.200.108:6789/SAMPLE" cn = DriverManager.getConnection( url, sUsr, sPwd );

    #?JDBC連接數(shù)據(jù)庫經(jīng)驗技巧集萃 2005-11-20 19:51 Cheng Ⅱ
    Java數(shù)據(jù)庫連接(JDBC)由一組用 Java 編程語言編寫的類和接口組成。JDBC 為工具/數(shù)據(jù)庫開發(fā)人員提供了一個標準的 API,使他們能夠用純Java API 來編寫數(shù)據(jù)庫應(yīng)用程序。然而各個開發(fā)商的接口并不完全相同,所以開發(fā)環(huán)境的變化會帶來一定的配置變化。本文主要集合了不同數(shù)據(jù)庫的連接方式。

      一、連接各種數(shù)據(jù)庫方式速查表

      下面羅列了各種數(shù)據(jù)庫使用JDBC連接的方式,可以作為一個手冊使用。

      1、Oracle8/8i/9i數(shù)據(jù)庫(thin模式)

    Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
    String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl為數(shù)據(jù)庫的SID
    String user="test";
    String password="test";
    Connection conn= DriverManager.getConnection(url,user,password);

      2、DB2數(shù)據(jù)庫

    Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();
    String url="jdbc:db2://localhost:5000/sample"; //sample為你的數(shù)據(jù)庫名
    String user="admin";
    String password="";
    Connection conn= DriverManager.getConnection(url,user,password);

      3、Sql Server7.0/2000數(shù)據(jù)庫

    Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
    String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb";
    //mydb為數(shù)據(jù)庫
    String user="sa";
    String password="";
    Connection conn= DriverManager.getConnection(url,user,password);

      4、Sybase數(shù)據(jù)庫

    Class.forName("com.sybase.jdbc.SybDriver").newInstance();
    String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDB為你的數(shù)據(jù)庫名
    Properties sysProps = System.getProperties();
    SysProps.put("user","userid");
    SysProps.put("password","user_password");
    Connection conn= DriverManager.getConnection(url, SysProps);

      5、Informix數(shù)據(jù)庫

    Class.forName("com.informix.jdbc.IfxDriver").newInstance();
    String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;
    user=testuser;password=testpassword"; //myDB為數(shù)據(jù)庫名
    Connection conn= DriverManager.getConnection(url);

      6、MySQL數(shù)據(jù)庫

    Class.forName("org.gjt.mm.mysql.Driver").newInstance();
    String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1"
    //myDB為數(shù)據(jù)庫名
    Connection conn= DriverManager.getConnection(url);

      7、PostgreSQL數(shù)據(jù)庫

    Class.forName("org.postgresql.Driver").newInstance();
    String url ="jdbc:postgresql://localhost/myDB" //myDB為數(shù)據(jù)庫名
    String user="myuser";
    String password="mypassword";
    Connection conn= DriverManager.getConnection(url,user,password);

      8、access數(shù)據(jù)庫直連用ODBC的

    Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
    String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");
    Connection conn = DriverManager.getConnection(url,"","");
    Statement stmtNew=conn.createStatement() ;

      二、JDBC連接MySql方式

      下面是使用JDBC連接MySql的一個小的教程

      1、查找驅(qū)動程序

      MySQL目前提供的java驅(qū)動程序為Connection/J,可以從MySQL官方網(wǎng)站下載,并找到mysql-connector-java-3.0.15-ga-bin.jar文件,此驅(qū)動程序為純java驅(qū)動程序,不需做其他配置。

      2、動態(tài)指定classpath

      如果需要執(zhí)行時動態(tài)指定classpath,就在執(zhí)行時采用-cp方式。否則將上面的.jar文件加入到classpath環(huán)境變量中。

      3、加載驅(qū)動程序

    try{
     Class.forName(com.mysql.jdbc.Driver);
     System.out.println(Success loading Mysql Driver!);
    }catch(Exception e)
    {
     System.out.println(Error loading Mysql Driver!);
     e.printStackTrace();
    }

      4、設(shè)置連接的url

    jdbc:mysql://localhost/databasename[?pa=va][&pa=va]



    #?談?wù)凧DBC接口技術(shù) 2005-11-20 19:52 Cheng Ⅱ
    JDBC是一種可用于執(zhí)行SQL語句的JavaAPI(ApplicationProgrammingInterface應(yīng)用程序設(shè)計接口)。它由一些Java語言編寫的類和界面組成。JDBC為數(shù)據(jù)庫應(yīng)用開發(fā)人員、數(shù)據(jù)庫前臺工具開發(fā)人員提供了一種標準的應(yīng)用程序設(shè)計接口,使開發(fā)人員可以用純Java語言編寫完整的數(shù)據(jù)庫應(yīng)用程序。

    一、ODBC到JDBC的發(fā)展歷程

    說到JDBC,很容易讓人聯(lián)想到另一個十分熟悉的字眼“ODBC”。它們之間有沒有聯(lián)系呢?如果有,那么它們之間又是怎樣的關(guān)系呢?

    ODBC是OpenDatabaseConnectivity的英文簡寫。它是一種用來在相關(guān)或不相關(guān)的數(shù)據(jù)庫管理系統(tǒng)(DBMS)中存取數(shù)據(jù)的,用C語言實現(xiàn)的,標準應(yīng)用程序數(shù)據(jù)接口。通過ODBCAPI,應(yīng)用程序可以存取保存在多種不同數(shù)據(jù)庫管理系統(tǒng)(DBMS)中的數(shù)據(jù),而不論每個DBMS使用了何種數(shù)據(jù)存儲格式和編程接口。

    1.ODBC的結(jié)構(gòu)模型
    ODBC的結(jié)構(gòu)包括四個主要部分:應(yīng)用程序接口、驅(qū)動器管理器、數(shù)據(jù)庫驅(qū)動器和數(shù)據(jù)源。
    應(yīng)用程序接口:屏蔽不同的ODBC數(shù)據(jù)庫驅(qū)動器之間函數(shù)調(diào)用的差別,為用戶提供統(tǒng)一的SQL編程接口。
    驅(qū)動器管理器:為應(yīng)用程序裝載數(shù)據(jù)庫驅(qū)動器。
    數(shù)據(jù)庫驅(qū)動器:實現(xiàn)ODBC的函數(shù)調(diào)用,提供對特定數(shù)據(jù)源的SQL請求。如果需要,數(shù)據(jù)庫驅(qū)動器將修改應(yīng)用程序的請求,使得請求符合相關(guān)的DBMS所支持的文法。
    數(shù)據(jù)源:由用戶想要存取的數(shù)據(jù)以及與它相關(guān)的操作系統(tǒng)、DBMS和用于訪問DBMS的網(wǎng)絡(luò)平臺組成。

    雖然ODBC驅(qū)動器管理器的主要目的是加載數(shù)據(jù)庫驅(qū)動器,以便ODBC函數(shù)調(diào)用,但是數(shù)據(jù)庫驅(qū)動器本身也執(zhí)行ODBC函數(shù)調(diào)用,并與數(shù)據(jù)庫相互配合。因此當(dāng)應(yīng)用系統(tǒng)發(fā)出調(diào)用與數(shù)據(jù)源進行連接時,數(shù)據(jù)庫驅(qū)動器能管理通信協(xié)議。當(dāng)建立起與數(shù)據(jù)源的連接時,數(shù)據(jù)庫驅(qū)動器便能處理應(yīng)用系統(tǒng)向DBMS發(fā)出的請求,對分析或發(fā)自數(shù)據(jù)源的設(shè)計進行必要的翻譯,并將結(jié)果返回給應(yīng)用系統(tǒng)。

    2.JDBC的誕生

    自從Java語言于1995年5月正式公布以來,Java風(fēng)靡全球。出現(xiàn)大量的用java語言編寫的程序,其中也包括數(shù)據(jù)庫應(yīng)用程序。由于沒有一個Java語言的API,編程人員不得不在Java程序中加入C語言的ODBC函數(shù)調(diào)用。這就使很多Java的優(yōu)秀特性無法充分發(fā)揮,比如平臺無關(guān)性、面向?qū)ο筇匦缘取kS著越來越多的編程人員對Java語言的日益喜愛,越來越多的公司在Java程序開發(fā)上投入的精力日益增加,對java語言接口的訪問數(shù)據(jù)庫的API的要求越來越強烈。也由于ODBC的有其不足之處,比如它并不容易使用,沒有面向?qū)ο蟮奶匦缘鹊龋琒UN公司決定開發(fā)一Java語言為接口的數(shù)據(jù)庫應(yīng)用程序開發(fā)接口。在JDK1.x版本中,JDBC只是一個可選部件,到了JDK1.1公布時,SQL類包(也就是JDBCAPI)就成為Java語言的標準部件。

    二、JDBC技術(shù)概述

    JDBC是一種可用于執(zhí)行SQL語句的JavaAPI(ApplicationProgrammingInterface,應(yīng)用程序設(shè)計接口)。它由一些Java語言寫的類、界面組成。JDBC給數(shù)據(jù)庫應(yīng)用開發(fā)人員、數(shù)據(jù)庫前臺工具開發(fā)人員提供了一種標準的應(yīng)用程序設(shè)計接口,使開發(fā)人員可以用純Java語言編寫完整的數(shù)據(jù)庫應(yīng)用程序。

    通過使用JDBC,開發(fā)人員可以很方便地將SQL語句傳送給幾乎任何一種數(shù)據(jù)庫。也就是說,開發(fā)人員可以不必寫一個程序訪問Sybase,寫另一個程序訪問Oracle,再寫一個程序訪問Microsoft的SQLServer。用JDBC寫的程序能夠自動地將SQL語句傳送給相應(yīng)的數(shù)據(jù)庫管理系統(tǒng)(DBMS)。不但如此,使用Java編寫的應(yīng)用程序可以在任何支持Java的平臺上運行,不必在不同的平臺上編寫不同的應(yīng)用。Java和JDBC的結(jié)合可以讓開發(fā)人員在開發(fā)數(shù)據(jù)庫應(yīng)用時真正實現(xiàn)“WriteOnce,RunEverywhere!”

    Java具有健壯、安全、易用等特性,而且支持自動網(wǎng)上下載,本質(zhì)上是一種很好的數(shù)據(jù)庫應(yīng)用的編程語言。它所需要的是Java應(yīng)用如何同各種各樣的數(shù)據(jù)庫連接,JDBC正是實現(xiàn)這種連接的關(guān)鍵。

    JDBC擴展了Java的能力,如使用Java和JDBCAPI就可以公布一個Web頁,頁中帶有能訪問遠端數(shù)據(jù)庫的Ap?plet。或者企業(yè)可以通過JDBC讓全部的職工(他們可以使用不同的操作系統(tǒng),如Windwos,Machintosh和UNIX)在In?tranet上連接到幾個全球數(shù)據(jù)庫上,而這幾個全球數(shù)據(jù)庫可以是不相同的。隨著越來越多的程序開發(fā)人員使用Java語言,對Java訪問數(shù)據(jù)庫易操作性的需求越來越強烈。

    MIS管理人員喜歡Java和JDBC,因為這樣可以更容易經(jīng)濟地公布信息。各種已經(jīng)安裝在數(shù)據(jù)庫中的事務(wù)處理都將繼續(xù)正常運行,甚至這些事務(wù)處理是存儲在不同的數(shù)據(jù)庫管理系統(tǒng)中;而對新的數(shù)據(jù)庫應(yīng)用來說,開發(fā)時間將縮短,安裝和版本升級將大大簡化。程序員可以編寫或改寫一個程序,然后將它放在服務(wù)器上,而每個用戶都可以訪問服務(wù)器得到最新的版本。對于信息服務(wù)行業(yè),Java和JDBC提供了一種很好的向外界用戶更新信息的方法。

    1.JDBC的任務(wù)

    簡單地說,JDBC能完成下列三件事:
    1)同一個數(shù)據(jù)庫建立連接;
    2)向數(shù)據(jù)庫發(fā)送SQL語句;
    3)處理數(shù)據(jù)庫返回的結(jié)果。

    2.JDBC一種底層的API

    JDBC是一種底層API,這意味著它將直接調(diào)用SQL命令。JDBC完全勝任這個任務(wù),而且比其他數(shù)據(jù)庫互聯(lián)更加容易實現(xiàn)。同時它也是構(gòu)造高層API和數(shù)據(jù)庫開發(fā)工具的基礎(chǔ)。高層API和數(shù)據(jù)庫開發(fā)工具應(yīng)該是用戶界面更加友好,使用更加方便,更易于理解的。但所有這樣的API將最終被翻譯為象JDBC這樣的底層API。目前兩種基于JDBC的高層API正處在開發(fā)階段。

    1)SQL語言嵌入Java的預(yù)處理器。雖然DBMS已經(jīng)實現(xiàn)了SQL查詢,但JDBC要求SQL語句被當(dāng)作字符串參數(shù)傳送給Java程序。而嵌入式SQL預(yù)處理器允許程序員將SQL語句混用:Java變量可以在SQL語句中使用,來接收或提供數(shù)值。然后SQL的預(yù)處理器將把這種Java/SQL混用的程序翻譯成帶有JDBCAPI的Java程序。

    2)實現(xiàn)從關(guān)系數(shù)據(jù)庫到Java類的直接映射。Javasoft和其他公司已經(jīng)宣布要實現(xiàn)這一技術(shù)。在這種“對象/關(guān)系”映射中,表的每一行都將變成這類的一個實例,每一列的值對應(yīng)實例的一個屬性。程序員可以直接操作Java的對象;而存取所需要的SQL調(diào)用將在內(nèi)部直接產(chǎn)生。還可以實現(xiàn)更加復(fù)雜的映射,比如多張表的行在一個Java的類中實現(xiàn)。

    隨著大家對JDBC興趣的不斷濃厚,越來越多的開發(fā)人員已經(jīng)開始利用JDBC為基礎(chǔ)的工具進行開發(fā)。這使開發(fā)工作變得容易。同時,程序員也正在開發(fā)對最終用戶來說訪問數(shù)據(jù)庫更加容易的應(yīng)用程序。

    3.JDBC和ODBC及其他API的比較

    到目前為止,微軟的ODBC可能是用得最廣泛的訪問關(guān)系數(shù)據(jù)庫的API。它提供了連接幾乎任何一種平臺、任何一種數(shù)據(jù)庫的能力。那么,為什么不直接從Java中直接使用ODBC呢?

    回答是可以從Java中使用ODBC,但最好在JDBC的協(xié)助下,用JDBC-ODBC橋接器實現(xiàn)。那么,為什么需要JDBC呢?要回答這個問題,有這么幾個方面:

    1)ODBC并不適合在Java中直接使用。ODBC是一個C語言實現(xiàn)的API,從Java程序調(diào)用本地的C程序會帶來一系列類似安全性、完整性、健壯性的缺點。

    2)其次,完全精確地實現(xiàn)從C代碼ODBC到JavaAPI寫的ODBC的翻譯也并不令人滿意。比如,Java沒有指針,而ODBC中大量地使用了指針,包括極易出錯的空指針“void*”。因此,對Java程序員來說,把JDBC設(shè)想成將ODBC轉(zhuǎn)換成面向?qū)ο蟮腁PI是很自然的。

    3)ODBC并不容易學(xué)習(xí),它將簡單特性和復(fù)雜特性混雜在一起,甚至對非常簡單的查詢都有復(fù)雜的選項。而JDBC剛好相反,它保持了簡單事物的簡單性,但又允許復(fù)雜的特性。

    4)JDBC這樣的JavaAPI對于純Java方案來說是必須的。當(dāng)使用ODBC時,人們必須在每一臺客戶機上安裝ODBC驅(qū)動器和驅(qū)動管理器。如果JDBC驅(qū)動器是完全用Java語言實現(xiàn)的話,那么JDBC的代碼就可以自動的下載和安裝,并保證其安全性,而且,這將適應(yīng)任何Java平臺,從網(wǎng)絡(luò)計算機NC到大型主機Mainframe。

    總而言之,JDBCAPI是能體現(xiàn)SQL最基本抽象概念的、最直接的Java接口。它建構(gòu)在ODBC的基礎(chǔ)上,因此,熟悉ODBC的程序員將發(fā)現(xiàn)學(xué)習(xí)JDBC非常容易。JDBC保持了ODBC的基本設(shè)計特征。實際上,這兩種接口都是基于X/OPENSQL的調(diào)用級接口(CLI)。它們的最大的不同是JDBC是基于Java的風(fēng)格和優(yōu)點,并強化了Java的風(fēng)格和優(yōu)點。

    最近,微軟又推出了除了ODBC以外的新的API,如RDO,ADO和OLEDB。這些API事實上在很多方面上同JDBC一樣朝著相同的方向努力,也就是努力成為一個面向?qū)ο蟮模贠DBC的類接口。然而,這些接口目前并不能代替ODBC,尤其在ODBC驅(qū)動器已經(jīng)在市場完全形成的時候,更重要的是它們只是ODBC的“漂亮的包裝”。

    4.JDBC兩層模型和三層模型

    JDBC支持兩層模型,也支持三層模型訪問數(shù)據(jù)庫。 兩層模型中,一個java Appple或者一個JA-va應(yīng)用直接同數(shù)據(jù)庫連接。這就需要能直接被訪問的數(shù)據(jù)庫進行連接的JDBC驅(qū)動器。用戶的SQL語句被傳送給數(shù)據(jù)庫,而這些語句執(zhí)行的結(jié)果將被傳回給用戶。數(shù)據(jù)庫可以在同一機器上,也可以另一機器上通過網(wǎng)絡(luò)進行連接。這被稱為“Client/Server”結(jié)構(gòu),用戶的計算機作為Client,運行數(shù)據(jù)庫的計算機作為Server。這個網(wǎng)絡(luò)可是intranet,比如連接全體雇員的企業(yè)內(nèi)部網(wǎng),當(dāng)然也可以是internet。

    在三層模型中,命令將被發(fā)送到服務(wù)的“中間層”,而“中間層”將SQL語句發(fā)送到數(shù)據(jù)庫。數(shù)據(jù)庫處理SQL語句并將結(jié)果返回“中間層”,然后“中間層”將它們 返回用戶。MIS管理員將發(fā)現(xiàn)三層模型很有吸引力,因為“中間層”可以進行對訪問的控制并協(xié)同數(shù)據(jù)庫的更新,另一個優(yōu)勢就是如果有一個“中間層”用戶就可以使用一個易用的高層的API,這個API可以由“中間層”進行轉(zhuǎn)換,轉(zhuǎn)換成底層的調(diào)用。而且,在許多情況下,三層模型可以提供更好的性能。

    到目前為止,“中間層”通常還是用C或C++實現(xiàn),以保證其高性能。但隨著優(yōu)化編譯器的引入,將java的字節(jié)碼轉(zhuǎn)換成高效的機器碼,用java來實現(xiàn)“中間層”將越來越實際。而JDBC是允許從一個java“中間層”訪問數(shù)據(jù)庫的關(guān)鍵。 (T111)
    posted on 2006-11-17 17:44 PrettyBoy 閱讀(556) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
    博客園   IT新聞   Chat2DB   C++博客   博問  
     
    主站蜘蛛池模板: 亚洲色欲www综合网| 亚洲人成影院在线观看| 三年片在线观看免费大全| 亚洲性线免费观看视频成熟| 成年女人免费v片| 免费人妻av无码专区| 亚洲综合精品网站| 一级成人生活片免费看| 日韩精品无码一区二区三区免费| 成人免费淫片在线费观看| 亚洲人精品亚洲人成在线| 中文字幕免费在线看| 毛片a级毛片免费观看品善网| 亚洲一卡2卡4卡5卡6卡在线99| 一级毛片免费视频网站| 国产精品亚洲mnbav网站 | 亚洲精品白色在线发布| 亚洲av成人无码网站…| 最近免费mv在线观看动漫| 永久免费bbbbbb视频| 久久精品国产亚洲av四虎| 小说区亚洲自拍另类| AV无码免费永久在线观看| 亚洲国产午夜中文字幕精品黄网站| 亚洲日产2021三区| 久久精品免费观看| 亚洲国产综合精品中文字幕| 精品国产福利尤物免费| 亚洲A∨午夜成人片精品网站| 亚洲国产成人无码av在线播放| 欧洲人免费视频网站在线| 亚洲色婷婷一区二区三区| 美美女高清毛片视频黄的一免费| 四虎1515hh永久久免费| 亚洲AV无码一区二区三区DV| 2021在线观看视频精品免费| 无码久久精品国产亚洲Av影片| 成人妇女免费播放久久久| 久久亚洲AV成人无码| 国产在线a不卡免费视频| 亚洲AV成人一区二区三区观看 |