欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
使用 JDBC 創(chuàng )建數據庫對象
本文分析了Java DataBase Connectivity (JDBC),一個(gè)在 Java 中以面向對象的方法來(lái)連接數據庫的技術(shù)。它是對 ODBC API 進(jìn)行的一種面向對象的封裝和重新設計,它易于學(xué)習和使用,并且它能夠使您編寫(xiě)不依賴(lài)供應商的代碼,用以查詢(xún)和操縱數據庫。JDBC 提供了一些相當低層的方法來(lái)存取數據庫,同時(shí)也在相當高層提供了功能強大的對象來(lái)處理數據庫。

什么是數據庫?

數據庫是以某種文件結構存儲的一系列信息表,這種文件結構使您能夠訪(fǎng)問(wèn)這些表、選擇表中的列、對表進(jìn)行排序以及根據各種標準選擇行。數據庫通常有多個(gè) 索引與這些表中的許多列相關(guān)聯(lián),所以我們能盡可能快地訪(fǎng)問(wèn)這些表。

在進(jìn)行計算時(shí),數據庫比其它類(lèi)型的結構更常用。您會(huì )發(fā)現在員工記錄和薪資系統中數據庫處于核心地位,在旅行計劃系統中以及在產(chǎn)品生產(chǎn)和銷(xiāo)售的整個(gè)過(guò)程中都可以發(fā)現數據庫。

以員工記錄為例,您可以設想一個(gè)含有員工姓名、地址、工資、扣稅以及津貼等內容的表。讓我們考慮一下這些內容可能如何組織在一起。您可以設想一個(gè)表包含員工姓名、地址和電話(huà)號碼。您希望保存的其它信息可能包括工資、工資范圍、上次加薪時(shí)間、下次加薪時(shí)間、員工業(yè)績(jì)評定等內容。

這些內容是否應保存在一個(gè)表格中?幾乎可以肯定不應該如此。不同類(lèi)別的員工的工資范圍可能沒(méi)有區別;這樣,您可以?xún)H將員工類(lèi)型儲存在員工記錄表中,而將工資范圍儲存在另一個(gè)表中,通過(guò)類(lèi)型編號與這個(gè)表關(guān)聯(lián)??紤]以下情況:

Key Lastname SalaryType SalaryType Min Max
1 Adams 2 1 30000 45000
2 Johnson 1 2 45000 60000
3 Smyth 3 3 60000 75000
4 Tully 1
5 Wolff 2

SalaryType 列中的數據引用第二個(gè)表。我們可以想象出許多種這樣的表,如用于存儲居住城市和每個(gè)城市的稅值、健康計劃扣除金額等的表。每個(gè)表都有一個(gè)主鍵列(如上面兩個(gè)表中最左邊的列)和若干數據列。在數據庫中建立表格既是一門(mén)藝術(shù),也是一門(mén)科學(xué)。這些表的結構由它們的 范式指出。我們通常說(shuō)表屬于第一、第二或第三范式,簡(jiǎn)稱(chēng)為1NF、2NF或3NF。

第一范式:表中的每個(gè)表元應該只有一個(gè)值(永遠不可能是一個(gè)數組)。(1NF)

第二范式:滿(mǎn)足1NF,并且每一個(gè)副鍵列完全依賴(lài)于主鍵列。這表示主鍵和該行中的剩余表元之間是1對1的關(guān)系。(2NF)

第三范式:滿(mǎn)足2NF,并且所有副鍵列是互相獨立的。任何一個(gè)數據列中包含的值都不能從其他列的數據計算得到。(3NF)

現在,幾乎所有的數據庫都是基于“第三范式(3NF)”創(chuàng )建的。這意味著(zhù)通常都有相當多的表,每個(gè)表中的信息列都相對較少。

從數據庫中獲取數據

假設我們希望生成一個(gè)包含員工及其工資范圍的表,在我們設計的一個(gè)練習中將使用這個(gè)表。這個(gè)表格不是直接存在在數據庫中,但可以通過(guò)向數據庫發(fā)出一個(gè)查詢(xún)來(lái)構建它。我們希望得到如下所示的一個(gè)表:

Name Min Max
Adams $45,000.00 $60,000.00
Johnson $30,000.00 $45,000.00
Smyth $60,000.00 $75,000.00
Tully $30,000.00 $45,000.00
Wolff $45,000.00 $60,000.00

或者,按照工資遞增的順序排序

Name Min Max
Tully $30,000.00 $45,000.00
Johnson $30,000.00 $45,000.00
Wolff $45,000.00 $60,000.00
Adams $45,000.00 $60,000.00
Smyth $60,000.00 $75,000.00

我們發(fā)現,獲得這些表的查詢(xún)形式如下所示

        SELECT DISTINCTROW Employees.Name, SalaryRanges.Min,                            SalaryRanges.Max FROM Employees INNER JOIN SalaryRanges ON Employees.SalaryKey = SalaryRanges.SalaryKey                            ORDER BY SalaryRanges.Min;                            

這種語(yǔ)言稱(chēng)為結構化查詢(xún)語(yǔ)言,即 SQL (一般讀作 "sequel" ),而且它是幾乎目前所有數據庫都可以使用的一種語(yǔ)言。這幾年已頒布了若于 SQL 標準,而且大多數 PC 數據庫支持大部分 ANSI 標準。 SQL-92 標準被認為是一種基礎標準,而且已更新多次。然而,沒(méi)有一種數據庫可以完美地支持后來(lái)的 SQL 版本,而且大多數數據庫都提供了多種 SQL 擴展,以支持他們數據庫獨有的性能。

數據庫的種類(lèi)

由于 PC 已成為主要的辦公工具,因此,已開(kāi)發(fā)出在 PC 上的大量流行的數據庫,這些數據庫都是可以自管理的。它們包括初級數據庫,如 MicrosoftWorks ,還包括更為復雜的數據庫,如 Approach 、 dBase 、 Borland Paradox 、 Microsoft Access 和 FoxBase 。

另一類(lèi)PC數據庫包括那些可由許多PC客戶(hù)機通過(guò)服務(wù)器訪(fǎng)問(wèn)的數據庫。其中包括IBM DB/2、Microsoft SQL Server、Oracle、Sybase、SQLBase和XDB。所有這些數據庫產(chǎn)品都支持多種相對類(lèi)似的SQL方言,因此,所有數據庫最初看起來(lái)好象可以互換。當然,它們 不能互換的原因是每種數據庫都有不同的性能特征,而且每一種都有不同的用戶(hù)界面和編程接口。您可能會(huì )想,既然它們都支持SQL,對它們進(jìn)行的編程也應該相似,但這是絕對錯誤的,因為每種數據庫都使用其自己方式接收SQL查詢(xún),并使用其自己的方式返回結果。這就自然引出了一種新一代的標準:ODBC

ODBC

如果我們能夠以某種方式編寫(xiě)不依賴(lài)于特定廠(chǎng)商的數據庫的代碼,并且能夠不改變自己的調用程序即可從這些數據庫中得到相同的結果,那將是一件很好的事。如果我們可以?xún)H為所有這些數據庫編寫(xiě)一些封裝,使它們具有相似的編程接口,這種對數據庫編程獨立于供應商的特性將很容易實(shí)現。

Microsoft于1992年首先嘗試了這一技巧,該公司發(fā)布了一個(gè)規范,稱(chēng)為對象數據庫連接性。這被認為是在Windows環(huán)境下連接所有數據庫的答案。與所有軟件的第一個(gè)版本相同,它也經(jīng)歷了一些發(fā)展的困擾,在1994年推出了另一個(gè)版本,該版本運行速度更快,而且更為穩定。它也是第一個(gè)32位的版本。另外,ODBC開(kāi)始向Windows之外的其它平臺發(fā)展,到目前為止,它在PC和工作站領(lǐng)域已十分普遍。幾乎每個(gè)主要的數據庫廠(chǎng)商都提供ODBC驅動(dòng)程序。

然而,ODBC并不是我們最初想象的靈丹妙藥。許多數據庫廠(chǎng)商都將ODBC作為其標準接口之外的“備選接口”,而且對ODBC的編程微不足道。與其它Windows編程一樣,它包括句柄、指針和選項,使其難以掌握。最后一點(diǎn),ODBC不是中立的標準。它由Microsoft公司開(kāi)發(fā),并由該公司不斷改進(jìn),而微軟同時(shí)也推出了我們所有人所使用的極具競爭性的軟件平臺,這使得ODBC的未來(lái)難以預測。

什么是JDBC?

JDBC 是一組首字母縮寫(xiě),曾經(jīng)代表 “Java DataBaseConnectivity” ,但現在它本身已成為一個(gè)商標符號。它是對 ODBC API 進(jìn)行的一種面向對象的封裝和重新設計,它易于學(xué)習和使用,并且它真正能夠使您編寫(xiě)不依賴(lài)廠(chǎng)商的代碼,用以查詢(xún)和操縱數據庫。盡管它與所有 Java API 一樣,都是面向對象的,但它并不是很高級別的對象集,在本章的剩余部分,我們將提出更高級別的方法。

除Microsoft之外,多數廠(chǎng)商都采用了JDBC,并為其數據庫提供了JDBC驅動(dòng)程序;這使您可輕松地真正編寫(xiě)幾乎完全不依賴(lài)數據庫的代碼。另外,JavaSoft和Intersolv已開(kāi)發(fā)了一種稱(chēng)為JDBC-ODBCBridge的產(chǎn)品,可使您連接還沒(méi)有直接的JDBC驅動(dòng)程序的數據庫。支持JDBC的所有數據庫必須至少可以支持SQL-92標準。這在很大程度上實(shí)現了跨數據庫和平臺的可移植性。

安裝和使用JDBC

JDBC 的類(lèi)都被歸到 java.sql

包中,在安裝 Java JDK 1.1 或更高版本時(shí)會(huì )自動(dòng)安裝。然而,如果您想使用 JDBC-ODBC 橋,還必須安裝兩個(gè)另外的程序包。首先,如果您使用 Windows95 ,則必須將您的 ODBC 驅動(dòng)程序升級為 32 位驅動(dòng)程序,您可從 Microsoft 的網(wǎng)站下載。這個(gè)驅動(dòng)程序在 Microsoft 的網(wǎng)站上很難找到;請搜索 DataAcc.exe 并進(jìn)行下載和安裝。

JDBC-ODBC驅動(dòng)程序可從Sun的Java網(wǎng)站( http://java.sun.com)輕松地找到并下載。在您擴充并安裝了這個(gè)驅動(dòng)程序后,必須執行下列步驟:

  1. \jdbc-odbc\classes; 路徑添加到您的PATH環(huán)境變量中。
  2. \jdbc-odbc\classes; 路徑添加到您的CLASSPATH環(huán)境變量中。
  3. 在Windows 95環(huán)境下,將它們放入autoexec.bat文件中,重新引導,以使所有設置生效。
  4. 在Windows NT環(huán)境下,將它們添加到“控制面板”中“系統”對象的“環(huán)境”選項卡中,退出并重新登錄,以使其生效。

JDBC驅動(dòng)程序的類(lèi)型

Java 程序連接數據庫的方法實(shí)際上有四種:
  1. JDBC-ODBC橋和ODBC驅動(dòng)程序--在這種方式下,這是一個(gè)本地解決方案,因為ODBC驅動(dòng)程序和橋代碼必須出現在用戶(hù)的每臺機器中。從根本上說(shuō)這是一個(gè)臨時(shí)解決方案。
  2.  

  3. 本機代碼和Java驅動(dòng)程序--它用另一個(gè)本地解決方案(該平臺上的Java可調用的本機代碼)取代 ODBC 和 JDBC-ODBC 橋。
  4.  

  5. JDBC網(wǎng)絡(luò )的純Java驅動(dòng)程序--由Java驅動(dòng)程序翻譯的JDBC形成傳送給服務(wù)器的獨立協(xié)議。然后,服務(wù)器可連接任何數量的數據庫。這種方法使您可能從客戶(hù)機Applet中調用服務(wù)器,并將結果返回到您的Applet。在這種情況下,中間件軟件提供商可提供服務(wù)器。
  6.  

  7. 本機協(xié)議Java驅動(dòng)程序-- Java驅動(dòng)程序直接轉換為該數據庫的協(xié)議并進(jìn)行調用。這種方法也可以通過(guò)網(wǎng)絡(luò )使用,而且可以在Web瀏覽器的Applet中顯示結果。在這種情況下,每個(gè)數據庫廠(chǎng)商將提供驅動(dòng)程序。

如果您希望編寫(xiě)代碼來(lái)處理 PC 客戶(hù)機數據庫,如 dBase 、 Foxbase 或 Access ,則您可能會(huì )使用第一種方法,并且擁有用戶(hù)機器上的所有代碼。更大的客戶(hù)機 - 服務(wù)器數據庫產(chǎn)品(如 IBM 的 DB2 )已提供了第 3 級別的驅動(dòng)程序。

兩層模型和三層模型

當數據庫和查詢(xún)它的應用程序在同一臺機器上,而且沒(méi)有服務(wù)器代碼的干預時(shí),我們將生成的程序稱(chēng)為 兩層模型。一層是應用程序,而另一層是數據庫。在 JDBC-ODBC 橋系統中通常是這種情況。

當一個(gè)應用程序或applet調用服務(wù)器,服務(wù)器再去調用數據庫時(shí),我們稱(chēng)其為 三層模型。當您調用稱(chēng)為“服務(wù)器”的程序時(shí)通常是這種情況。

編寫(xiě)JDBC代碼訪(fǎng)問(wèn)數據庫

現在,我們將開(kāi)始看一下如何編寫(xiě) Java 程序來(lái)訪(fǎng)問(wèn)數據庫。我們要使用的數據庫是一個(gè)稱(chēng)為 groceries.mdb 的 Microsoft Access 數據庫。此數據庫中的數據由三個(gè)本地雜貨店中一些常見(jiàn)商品的價(jià)格組成。食品表如下所示:

FoodKey FoodName
1 Apples
2 Oranges
3 Hamburger
4 Butter
5 Milk
6 Cola
7 Greenbeans

雜貨店表如下所示:

StoreKey StoreName
1 Stop andShop
2 VillageMarket
3 Waldbaum‘s

雜貨店定價(jià)表僅由這三個(gè)表格中的鍵值和價(jià)格組成:

FSKey StoreKey FoodKey Price
1 1 1 $0.27
2 2 1 $0.29
3 3 1 $0.33
4 1 2 $0.36
5 2 2 $0.29
6 3 2 $0.47
7 1 3 $1.98
8 2 3 $2.45
9 3 3 $2.29
10 1 4 $2.39
11 2 4 $2.99
12 3 4 $3.29
13 1 5 $1.98
14 2 5 $1.79
15 3 5 $1.89
16 1 6 $2.65
17 2 6 $3.79
18 3 6 $2.99
19 1 7 $2.29
20 2 7 $2.19
21 3 7 $1.99

用ODBC注冊您的數據庫

在 Windows 95 或 NT 環(huán)境下訪(fǎng)問(wèn) ODBC 數據庫之前,必須使用控制面板中的 ODBC 驅動(dòng)程序對它進(jìn)行注冊。在 Windows 95 環(huán)境下,就是 “ 控制面板 ” 程序中的 ODBC 圖標。在 Windows NT 環(huán)境下,您會(huì )在 “ 開(kāi)始 ” 菜單中找到此程序。(如果找不到,您需要安裝上述的 ODBC 驅動(dòng)程序,即 WX1350.exe )。

雙擊ODBC圖標,然后單擊“添加”,如圖1所示。然后選擇數據庫驅動(dòng)程序(此處使用MicrosoftAccess),然后單擊“確定”。在“數據源名”和“描述”中分別鍵入數據源名稱(chēng)(Groceries)和數據庫說(shuō)明(Groceryprices)(這兩項都不需要和文件名相關(guān)),然后單擊“選取”,找到數據庫,并選擇該數據庫。找到該數據庫后,屏幕將如圖2所示。單擊“確定”,然后單擊“關(guān)閉”來(lái)關(guān)閉面板。



圖1:ODBC控制面板設置屏幕。



圖2:在ODBC控制面板中選擇數據庫和說(shuō)明。


連接數據庫

所有與數據庫有關(guān)的對象和方法都在 java.sql 包中,因此在使用 JDBC 的程序中必須加入 "import java.sql.* " 。 JDBC 要連接 ODBC 數據庫,您必須首先加載 JDBC-ODBC 橋驅動(dòng)程序

          Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");                            

該語(yǔ)句加載驅動(dòng)程序,并創(chuàng )建該類(lèi)的一個(gè)實(shí)例。然后,要連接一個(gè)特定的數據庫,您必須創(chuàng )建 Connect 類(lèi)的一個(gè)實(shí)例,并使用 URL 語(yǔ)法連接數據庫。

        String url = "jdbc:odbc:Grocery prices";                            Connection con = DriverManager.getConnection(url);                            

請注意,您使用的數據庫名是您在 ODBC 設置面板中輸入的 “ 數據源 ” 名稱(chēng)。

URL語(yǔ)法可能因數據庫類(lèi)型的不同而變化極大。

        jdbc:                            subprotocol:                            subname                            

第一組字符代表連接 協(xié)議,并且始終是 jdbc 。還可能有一個(gè) 子協(xié)議,在此處,子協(xié)議被指定為 odbc 。它規定了一類(lèi)數據庫的連通性機制。如果您要連接其它機器上的數據庫服務(wù)器,可能也要指定該機器和一個(gè)子目錄:
        jdbc:bark//doggie/elliott                            

最后,您可能要指定用戶(hù)名和口令,作為連接字符串的一部分:
        jdbc:bark//doggie/elliot;UID=GoodDog;PWD=woof                            

訪(fǎng)問(wèn)數據庫

一旦連接到數據庫,就可以請求表名以及表列的名稱(chēng)和內容等信息,而且您可以運行 SQL 語(yǔ)句來(lái)查詢(xún)數據庫或者添加或修改其內容??捎脕?lái)從數據庫中獲取信息的對象有:

DatabaseMetaData 有關(guān)整個(gè)數據庫的信息:表名、表的索引、數據庫產(chǎn)品的名稱(chēng)和版本、數據庫支持的操作。
ResultSet 關(guān)于某個(gè)表的信息或一個(gè)查詢(xún)的結果。您必須逐行訪(fǎng)問(wèn)數據行,但是您可以任何順序訪(fǎng)問(wèn)列。
ResultSetMetaData 有關(guān)ResultSet中列的名稱(chēng)和類(lèi)型的信息。

盡管每個(gè)對象都有大量的方法讓您獲得數據庫元素的極為詳細的信息,但在每個(gè)對象中都有幾種主要的方法使您可獲得數據的最重要信息。然而,如果您希望看到比此處更多的信息,建議您學(xué)習文檔以獲得其余方法的說(shuō)明。

ResultSet

ResultSet 對象是 JDBC 中最重要的單個(gè)對象。從本質(zhì)上講,它是對一個(gè)一般寬度和未知長(cháng)度的表的一種抽象。幾乎所有的方法和查詢(xún)都將數據作為 ResultSet 返回。 ResultSet 包含任意數量的命名列,您可以按名稱(chēng)訪(fǎng)問(wèn)這些列。它還包含一個(gè)或多個(gè)行,您可以按順序自上而下逐一訪(fǎng)問(wèn)。在您使用 ResultSet 之前,必須查詢(xún)它包含多少個(gè)列。此信息存儲在 ResultSetMetaData 對象中。

        //                            從元數據中獲得列數                            ResultSetMetaData rsmd;                            rsmd = results.getMetaData();                            numCols = rsmd.getColumnCount();                            

當您獲得一個(gè)ResultSet時(shí),它正好指向第一行之前的位置。您可以使用 next() 方法得到其他每一行,當沒(méi)有更多行時(shí),該方法會(huì )返回 false 。由于從數據庫中獲取數據可能會(huì )導致錯誤,您必須始終將結果集處理語(yǔ)句包括在一個(gè) try 塊中。

        try                            {                            rsmd = results.getMetaData();                            numCols = rsmd.getColumnCount();                            boolean more = results.next();                            while (more)                            {                            for (i = 1; i <= numCols; i++)                            System.out.print(results.getString(i)+" ");                            System.out.println();                            more = results.next();                            }                            results.close();                            }                            catch(Exception e)                            {System.out.println(e.getMessage());}                            

您可以多種形式獲取 ResultSet 中的數據,這取決于每個(gè)列中存儲的數據類(lèi)型。另外,您可以按列序號或列名獲取列的內容。請注意,列序號從 1 開(kāi)始,而不是從 0 開(kāi)始。 ResultSet 對象的一些最常用方法如下所示。

getInt(int); 將序號為 int 的列的內容作為整數返回。
getInt(String); 將名稱(chēng)為 String 的列的內容作為整數返回。
getFloat(int); 將序號為 int 的列的內容作為一個(gè) float 型數返回。
g<tt>etFloat(String);</tt> 將名稱(chēng)為 String 的列的內容作為 float 型數返回。
getDate(int); 將序號為 int 的列的內容作為日期返回。
getDate(String); 將名稱(chēng)為 String 的列的內容作為日期返回。
next(); 將行指針移到下一行。如果沒(méi)有剩余行,則返回 false 。
close(); 關(guān)閉結果集。
getMetaData(); 返回 ResultSetMetaData 對象。

ResultSetMetaData

您使用 getMetaData() 方法從 ResultSet 中獲取 ResultSetMetaData 對象。您可以使用此對象獲得列的數目和類(lèi)型以及每一列的名稱(chēng)。

              getColumnCount();                                        

返回 ResultSet 中的列數。
getColumnName(int); 返回列序號為 int 的列名。
getColumnLabel(int); 返回此列暗含的標簽。
isCurrency(int); 如果此列包含帶有貨幣單位的一個(gè)數字,則返回 true 。
isReadOnly(int); 如果此列為只讀,則返回 true 。
isAutoIncrement(int); 如果此列自動(dòng)遞增,則返回 true 。這類(lèi)列通常為鍵,而且始終是只讀的。
getColumnType(int); 返回此列的SQL數據類(lèi)型。這些數據類(lèi)型包括

BIGINT
BINARY
BIT
CHAR
DATE
DECIMAL
DOUBLE
FLOAT
INTEGER
LONGVARBINARY
LONGVARCHAR

NULL
NUMERIC
OTHER
REAL
SMALLINT
TIME
TIMESTAMP
TINYINT
VARBINARY
VARCHAR

DatabaseMetaData

DatabaseMetaData

對象可為您提供整個(gè)數據庫的信息。您主要用它獲取數據庫中表的名稱(chēng),以及表中列的名稱(chēng)。由于不同的數據庫支持不同的 SQL 變體,因此,也有多種方法查詢(xún)數據庫支持哪些 SQL 方法。

getCatalogs() 返回該數據庫中的信息目錄列表。使用 JDBC-ODBC Bridge 驅動(dòng)程序,您可以獲得用 ODBC 注冊的數據庫列表。這很少用于 JDBC-ODBC 數據庫。
getTables(catalog, schema, tableNames, columnNames) 返回表名與 tableNames 相符而且列名與 columnNames 相符的所有表的說(shuō)明。
getColumns(catalog, schema, tableNames,columnNames) 返回表名與 tableNames 相符而且列名與 columnNames 相符的所有表列說(shuō)明。
getURL(); 獲得您所連接的URL名稱(chēng)。
getDriverName(); 獲得您所連接的數據庫驅動(dòng)程序的名稱(chēng)。

獲取有關(guān)表的信息

您可以使用 DataBaseMetaData 的 getTables() 方法來(lái)獲取數據庫中表的信息。這個(gè)方法有如下 4 個(gè) String 參數:

        results =                            dma.getTables(catalog, schema, tablemask, types[]);                            

其中參數的意義是:

catalog 要在其中查找表名的目錄名。對于 JDBC-ODBC 數據庫以及許多其他數據庫而言,可將其設置為 null。這些數據庫的目錄項實(shí)際上是它在文件系統中的絕對路徑名稱(chēng)。
schema 要包括的數據庫“方案”。許多數據庫不支持方案,而對另一些數據庫而言,它代表數據庫所有者的用戶(hù)名。一般將它設置為 null 。
tablemask 一個(gè)掩碼,用來(lái)描述您要檢索的表的名稱(chēng)。如果您希望檢索所有表名,則將其設為通配符 % 。 請注意, SQL 中的通配符是 %符號,而不是一般PC用戶(hù)的*符號。
types[] 這是描述您要檢索的表的類(lèi)型的String數組。數據庫中通常包括許多用于內部處理的表,而對作為用戶(hù)的您沒(méi)什么價(jià)值。如果它是空值,則您會(huì )得到所有這些表。如果您將其設為包含字符串“ TABLES ”的單元素數組,您將僅獲得對用戶(hù)有用的表格。

用于從數據庫中獲取表名的簡(jiǎn)單代碼相當于獲取 DatabaseMetaData 對象,并從其中檢索表名:

        con = DriverManager.getConnection(url);                            //獲取數據庫的元數據                            dma =con.getMetaData();                            //將數據庫中的表的名稱(chēng)轉儲出來(lái)                            String[] types = new String[1];                            types[0] = "TABLES"; //設置查詢(xún)類(lèi)型                            //請注意通配符是                            % 符號(而不是                            “*”)                            results = dma.getTables(null, null, "%", types);                            

然后,我們可以打印出表名,正如我們上面所做的那樣:

        boolean more = results.next();                            while (more)                            {                            for (i = 1; i <= numCols; i++)                            System.out.print(results.getString(i)+" ");                            System.out.println();                            more = results.next();                            }                            

如前文所述,將所有代碼包括在 try 塊中。

執行SQL查詢(xún)

我們已經(jīng)理解了 JDBC 的基本對象,現在就可以執行 SQL 查詢(xún)了。查詢(xún)是作為 Statement 對象的方法執行的,您很容易從 Connection 對象獲得 Statement 對象:

        String query = "SELECT FoodName FROM Food;";                            ResultSet results;                            try                            {                            Statement stmt = con.createStatement();                            results = stmt.executeQuery(query);                            }                            catch (Exception e)                            {System.out.println("query exception");}                            

請注意,這個(gè)簡(jiǎn)單的查詢(xún)返回 Food 表中的整個(gè) FoodName 列。您使用像這樣的簡(jiǎn)單查詢(xún)獲取整個(gè)列的內容。請注意,查詢(xún)的查詢(xún)本身是一個(gè) ResultSet ,您可以用我們上面剛討論過(guò)的方法對它進(jìn)行處理。

打印ResultSet

因為我們總是要從 ResultSets 中打印數據,我們可以設計一種簡(jiǎn)單的方法,將整個(gè) ResultSet 轉儲出來(lái),包括表名稱(chēng)元數據。該子程序如下所示:

        private void dumpResults(String head)                            {                            //                            這是打印列標頭和每列的內容的                            //                            通用方法                            System.out.println(head);                            try                            {                            //                            從元數據中獲取列數                            rsmd = results.getMetaData();                            numCols = rsmd.getColumnCount();                            //                            打印列名                            for (i = 1; i<= numCols; i++)                            System.out.print(rsmd.getColumnName(i)+" ");                            System.out.println();                            //                            打印列內容                            boolean more = results.next();                            while (more)                            {                            for (i = 1; i <= numCols; i++)                            System.out.print(results.getString(i)+" ";                            System.out.println();                            more = results.next();                            }                            }                            catch(Exception e)                            {System.out.println(e.getMessage());}                            }                            

一個(gè)簡(jiǎn)單的JDBC程序

我們已經(jīng)學(xué)習了 JDBC 的所有基本功能,現在我們可以編寫(xiě)一個(gè)簡(jiǎn)單的程序,該程序打開(kāi)數據庫,打印它的表名以及某一表列的內容,然后對該數據庫執行查詢(xún)。此程序如下所示:

        import java.net.URL;                            import java.sql.*;                            import java.util.*;                            class JdbcOdbc_test                            {                            ResultSet results;                            ResultSetMetaData rsmd;                            DatabaseMetaData dma;                            Connection con;                            int numCols, i;                            //--                            public JdbcOdbc_test()                            {                            String url = "jdbc:odbc:Grocery prices";                            String query = "SELECT DISTINCTROW FoodName FROM Food " + "WHERE (FoodName like ‘C%‘);";                            try                            {                            //                            加載 JDBC-ODBC 橋驅動(dòng)程序                            Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");                            //連接數據庫                            con = DriverManager.getConnection(url);                            //獲取數據庫的元數據                            dma =con.getMetaData();                            System.out.println("Connected to:"+dma.getURL());                            System.out.println("Driver "+dma.getDriverName());                            //將數據庫中的表的名稱(chēng)轉儲出來(lái)                            String[] types = new String[1];                            types[0] = "TABLES";                            //請注意通配符是 % 符號(而不是“*”)                            results = dma.getTables(null, null, "%", types);                            dumpResults("--Tables--");                            results.close();                            }                            catch (Exception e)                            {System.out.println(e);}                            //獲取表列的名稱(chēng)                            System.out.println("--Column Names--");                            try {                            results =                            dma.getColumns(null, null, "FoodPrice", null);                            ResultSetMetaData rsmd = results.getMetaData();                            int numCols = rsmd.getColumnCount();                            while (results.next() )                            String cname = results.getString("COLUMN_NAME");                            System.out.print(cname + " ");                            System.out.println();                            results.close();                            }                            catch (Exception e)                            {System.out.println(e);}                            //列出一個(gè)列的內容 -- 這是一個(gè)查詢(xún)                            try {                            Statement stmt = con.createStatement();                            results =                            stmt.executeQuery("SELECT FOODNAME FROM FOOD;");                            }                            catch (Exception e)                            {System.out.println("query exception");}                            dumpResults("--Contents of FoodName column--");                            //嘗試實(shí)際的 SQL 語(yǔ)句                            try                            {                            Statement stmt = con.createStatement();                            results = stmt.executeQuery(query);                            }                            catch (Exception e)                            {System.out.println("query exception");}                            dumpResults("--Results of Query--");                            }                            

該程序打印出的結果如下所示:

        C:\Projects\objectJava\chapter19>java JdbcOdbc_test                            Connected to:jdbc:odbc:Grocery prices                            Driver JDBC-ODBC Bridge (ODBCJT32.DLL)                            --Tables--                            TABLE_QUALIFIER TABLE_OWNER TABLE_NAME TABLE_TYPE REMARKS                            groceries null Food TABLE null                            groceries null FoodPrice TABLE null                            groceries null Stores TABLE null                            --Column Names--                            FSKey StoreKey FoodKey Price                            --Contents of FoodName column--                            FOODNAME                            Apples                            Oranges                            Hamburger                            Butter                            Milk                            Cola                            Green beans                            --Results of Query--                            FoodName                            Cola                            

構建更高級別的JDBC對象

從上面的例子可以明顯看出,如果可以將我們使用過(guò)的一些方法封裝在幾個(gè)更高級別對象中,那將非常有幫助,我們不僅可以封裝 try 程序塊,而且可以更簡(jiǎn)單地訪(fǎng)問(wèn) ResultSet 方法。

在這一部分中,我們將構建一個(gè)新的 resultSet 對象,該對象封裝了JDBC ResultSet 對象,并以String數組的形式返回一行數據。我們發(fā)現您始終需要從 ResultSetMetaData 對象中獲取列的序號和名稱(chēng),因此,創(chuàng )建一個(gè)封裝元數據的新對象就非常合理。

另外,我們經(jīng)常需要按名稱(chēng)或整數索引提取某行的元素,如果不必總是將這些訪(fǎng)問(wèn)語(yǔ)句包括 try 塊中,那將大有幫助。最后一點(diǎn),如果我們需要整行的內容,則更方便的做法是將整行以String數組形式返回。在下面所示的 resultSet 對象中,我們致力于實(shí)現這些目標:

        class resultSet                            {                            //                            這個(gè)類(lèi)是                            JDBC ResultSet                            對象的更高級抽象                            ResultSet rs;                            ResultSetMetaData rsmd;                            int numCols;                            public resultSet(ResultSet rset)                            {                            rs = rset;                            try                            {                            //                            同時(shí)獲取元數據和列數                            rsmd = rs.getMetaData();                            numCols = rsmd.getColumnCount();                            }                            catch (Exception e)                            {System.out.println("resultset error"                            +e.getMessage());}                            }                            //--                            public String[] getMetaData()                            {                            //                            返回包含所有列名或其他元數據的                            //                            一個(gè)數組                            String md[] = new String[numCols];                            try                            {                            for (int i=1; i<= numCols; i++)                            md[i-1] = rsmd.getColumnName(i);                            }                            catch (Exception e)                            {System.out.println("meta data error"+                            e.getMessage());}                            return md;                            }                            //--                            public boolean hasMoreElements()                            {                            try{                            return rs.next();                            }                            catch(Exception e){return false;}                            }                            //--                            public String[] nextElement()                            {                            //                            將行的內容復制到字符串數組中                            String[] row = new String[numCols];                            try                            {                            for (int i = 1; i <= numCols; i++)                            row[i-1] = rs.getString(i);                            }                            catch (Exception e)                            {System.out.println("next element error"+                            e.getMessage());}                            return row;                            }                            //--                            public String getColumnValue(String columnName)                            {                            String res = "";                            try                            {                            res = rs.getString(columnName);                            }                            catch (Exception e)                            {System.out.println("Column value error:"+                            columnName+e.getMessage());}                            return res;                            }                            //--                            public String getColumnValue(int i)                            {                            String res = "";                            try                            {                            res = rs.getString(i);                            }                            catch (Exception e)                            {System.out.println("Column value error:"+                            columnName+e.getMessage());}                            return res;                            }                            //--                            public void finalize()                            {                            try{rs.close();}                            catch (Exception e)                            {System.out.println(e.getMessage());}                            }                            }                            

通過(guò)簡(jiǎn)單使用 new 操作符就地創(chuàng )建一個(gè) ResultSet 對象,我們很容易將任何 ResultSet 對象封裝在此類(lèi)中:

        ResultSet results = .. //                            按通常的方法獲得                            ResultsSet                            //                            利用它創(chuàng  )建一個(gè)更有用的對象                            resultSet rs = new resultSet(results);                            

并很容易在任何 JDBC 程序中使用這個(gè)對象。

構建一個(gè)Database對象

我們沿 00 鏈向上移的另一部分努力是創(chuàng )建一個(gè) Database 對象,它將封裝下列對象的行為: Connection 、 Statement DatabaseMetaData 對象, 以及我們剛剛構建的 SQL 查詢(xún)和 resultSet 。我們的 Database 對象允許我們創(chuàng )建連接、獲取表名、在數據庫中移動(dòng)以及更簡(jiǎn)單地獲得行和列的值。請注意, Execute 方法返回一個(gè) resultSet 對象,您可以直接對它進(jìn)行操作。

        class Database                            {                            //                            這是一個(gè)將                            JDBC                            數據庫的所有功能封裝在單個(gè)對象中的類(lèi)                            Connection con;                            resultSet results;                            ResultSetMetaData rsmd;                            DatabaseMetaData dma;                            String catalog;                            String types[];                            public Database(String driver)                            {                            types = new String[1];                            types[0] = "TABLES"; //                            初始化類(lèi)型                            try{Class.forName(driver);} //                            加載                            JDBC-ODBC                            橋驅動(dòng)程序                            catch (Exception e)                            {System.out.println(e.getMessage());}                            }                            //--                            public void Open(String url, String cat)                            {                            catalog = cat;                            try {con = DriverManager.getConnection(url);                            dma =con.getMetaData(); //                            獲取元數據                            }                            catch (Exception e)                            {System.out.println(e.getMessage());}                            }                            //--                            public String[] getTableNames()                            {                            String[] tbnames = null;                            Vector tname = new Vector();                            //                            將表名添加到一個(gè) Vector                            中,                            //                            因為我們不知道有多少個(gè)表                            try {                            results =                            new resultSet(dma.getTables(catalog, null,                            "%", types));                            while (results.hasMoreElements())                            tname.addElement(results.getColumnValue("TABLE_NAME"));                            }                            catch (Exception e) {System.out.println(e);}                            //                            將表名復制到一個(gè)                            String                            數組中                            tbnames = new String[tname.size()];                            for (int i=0; i< tname.size(); i++)                            tbnames[i] = (String)tname.elementAt(i);                            return tbnames;                            }                            //--                            public String[] getTableMetaData()                            {                            //                            返回表類(lèi)型的信息                            results = null;                            try{                            results =                            new resultSet(dma.getTables(catalog, null,                            "%", types));                            }                            catch (Exception e)                            {System.out.println(e.getMessage());}                            return results.getMetaData();                            }                            //--                            public String[] getColumnMetaData(String tablename)                            {                            //                            返回一個(gè)列的數據                            results = null;                            try {                            results =                            new resultSet(dma.getColumns(catalog, null,                            tablename, null));                            }                            catch (Exception e)                            {System.out.println(e.getMessage());}                            return results.getMetaData();                            }                            //--                            public String[] getColumnNames(String table)                            {                            //                            返回一個(gè)列名數組                            String[] tbnames = null;                            Vector tname = new Vector();                            try {                            results =                            new resultSet(dma.getColumns(catalog, null,                            table, null));                            while (results.hasMoreElements() )                            tname.addElement(results.getColumnValue("COLUMN_NAME"));                            }                            catch (Exception e) {System.out.println(e);}                            tbnames = new String[tname.size()];                            for (int i=0; i< tname.size(); i++)                            tbnames[i] = (String)tname.elementAt(i);                            return tbnames;                            }                            //--                            public String getColumnValue(String table,                            String columnName)                            {                            //                            返回給定列的值                            String res = null;                            try                            {                            if (table.length()>0)                            results =                            Execute("Select " + columnName +                            " from " + table +                            " order by "+columnName);                            if (results.hasMoreElements())                            res = results.getColumnValue(columnName);                            }                            catch (Exception e)                            {System.out.println("Column value error" +                            columnName+ e.getMessage());}                            return res;                            }                            //--                            public String getNextValue(String columnName)                            {                            //                            使用存儲的                            resultSet                            //                            返回該列的下一個(gè)值                            String res = "";                            try                            {                            if (results.hasMoreElements())                            res = results.getColumnValue(columnName);                            }                            catch (Exception e)                            {System.out.println("next value error"+                            columnName+ e.getMessage());}                            return res;                            }                            //--                            public resultSet Execute(String sql)                            {                            //                            對此數據庫執行一個(gè)                            SQL                            查詢(xún)                            results = null;                            try                            {                            Statement stmt = con.createStatement();                            results = new resultSet(stmt.executeQuery(sql));                            }                            catch (Exception e)                            {System.out.println("execute error"+                            e.getMessage());}                            return results;                            }                            }                            

一個(gè)可視化的數據庫程序

為了對我們本章學(xué)習的內容進(jìn)行總結,我們編寫(xiě)一個(gè)簡(jiǎn)單的 GUI 程序,它可以顯示數據庫的表名、列名和列內容。我們還將包括一個(gè)文本區域,您可以在其中鍵入一個(gè)要對數據庫執行的 SQL 查詢(xún)。在 Companion CD-ROM 上的 \chapter20 子目錄中,可以找到本程序(稱(chēng)為 dbFrame.java )所使用的 resultSet Database 類(lèi)。程序的顯示界面如圖 3 所示。



圖3:用來(lái)顯示用JDBC連接的數據庫中的數據的dbFrame.java程序。

在本程序中,默認數據庫(groceries.mdb)的表名顯示在左側的欄中。當您單擊其中一個(gè)表名時(shí),列名就會(huì )顯示在中間的欄中。最后,當您單擊中間欄中的某一行時(shí),該行的內容就會(huì )顯示在右側的欄中。

本程序的關(guān)鍵只是接收列表選擇,然后清除并填充正確的列表框:

        public void itemStateChanged(ItemEvent e)                            {                            Object obj = e.getSource();                            if (obj == Tables) //                            放入列名                            showColumns();                            if (obj == Columns) //                            放入列的內容                            showData();                            }                            //--                            private void loadList(List list, String[] s)                            {                            //                            清除并填充指定的列表框                            list.removeAll();                            for (int i=0; i< s.length; i++)                            list.add(s[i]);                            }                            //--                            private void showColumns()                            {                            //                            顯示列名                            String cnames[] =                            db.getColumnNames(Tables.getSelectedItem());                            loadList(Columns, cnames);                            }                            //--                            private void showData()                            {                            String colname = Columns.getSelectedItem();                            String colval =                            db.getColumnValue(Tables.getSelectedItem(),                            colname);                            Data.setVisible(false);                            Data.removeAll();                            Data.setVisible(true);                            colval =                            db.getNextValue(Columns.getSelectedItem());                            while (colval.length()>0)                            {                            Data.add(colval);                            colval =                            db.getNextValue(Columns.getSelectedItem());                            }                            }                            

執行查詢(xún)

顯示畫(huà)面底部的文本區域使您可鍵入所需的任何 SQL 查詢(xún)。演示程序中構建的一個(gè)查詢(xún)如下所示:

        String queryText =                            "SELECT DISTINCTROW FoodName, StoreName, Price "+                            "FROM (Food INNER JOIN FoodPrice ON "+                            "Food.FoodKey = FoodPrice.FoodKey) " +                            "INNER JOIN Stores ON "+                            "FoodPrice.StoreKey = Stores.StoreKey "+                            "WHERE (((Food.FoodName)=\‘Oranges\‘)) "+                            " ORDER BY FoodPrice.Price;";                            

此查詢(xún)簡(jiǎn)單地列出每個(gè)雜貨店的桔子價(jià)格。

當您單擊 Run Query按鈕時(shí),它將執行此查詢(xún),并將resultSet對象傳送給一個(gè)對話(huà)框進(jìn)行顯示:

        public void actionPerformed(ActionEvent e)                            {                            Object obj = e.getSource();                            if (obj == Quit)                            System.exit(0);                            if (obj == Search)                            clickedSearch();                            }                            //--                            private void clickedSearch()                            {                            resultSet rs = db.Execute(query.getText());                            String cnames[] = rs.getMetaData();                            queryDialog q = new queryDialog(this, rs);                            q.show();                            }                            

查詢(xún)結果對話(huà)框

查詢(xún)對話(huà)框獲得 resultSet 對象,并將每一行放入一個(gè) String 數組中,然后將這些 String 數組放入一個(gè) Vector 中,這樣就可以在 paint() 子程序運行期間快速訪(fǎng)問(wèn)這些行。

        private void makeTables()                            {                            //                            將每一行放入一個(gè)                            String                            數組中,并將                            //                            這些字符串數組全部放入一個(gè)                            Vector                            中                            tables = new Vector();                            String t[] = results.getMetaData();                            tables.addElement( t);                            while (results.hasMoreElements())                            tables.addElement(results.nextElement());                            }                            

我們通過(guò) Graphics 的 drawString() 方法將數據繪制在一個(gè) Panel 中。就像在 Printer 對象中一樣,我們必須自己跟蹤 x 和 y 的位置。

        public void paint(Graphics g)                            {                            String s[];                            int x=0;                            //                            計算字體的高度                            int y =g.getFontMetrics().getHeight();                            //                            估算列的高度                            int deltaX = (int)1.5f*                            (g.getFontMetrics().stringWidth("wwwwwwwwwwwwww"));                            //                            遍歷表矢量                            for (int i=0; i< tables.size(); i++)                            {                            s = (String[])tables.elementAt(i);                            //                            繪制字符串數組中的每一行                            for (int j =0; j< s.length; j++)                            {                            String st= s[j];                            g.drawString(st, x, y);                            x += deltaX; //                            移到下一列                            }                            x = 0; //                            開(kāi)始一個(gè)新行                            y += g.getFontMetrics().getHeight();                            //                            列標簽與列數據之間的額外空間                            if (i == 0) y += g.getFontMetrics().getHeight();                            }                            }                            

內建查詢(xún)的 queryDialog 如圖 4 所示。



圖4:dbFrame程序中 顯示的queryDialog,其中顯示的是默認查詢(xún)的結果。

示例文件

groceries.zip
dbFrame.zip
jdbc-odbc Bridge

小結

在本文中,我們討論了數據庫以及檢驗數據庫并對數據庫執行查詢(xún)的方法。我們已經(jīng)看到, JDBC 提供了一種與平臺和數據庫無(wú)關(guān)的、面向對象的方法來(lái)訪(fǎng)問(wèn)這些數據,我們還學(xué)習了 JDBC 的主要對象: ResultSet 、 ResultSetMetaData DatabaseMetaData。 在用這些對象編寫(xiě)了一個(gè)簡(jiǎn)單的程序之后,我們設計了更高級別的 resultSet Database 對象,我們用它們構建了一個(gè)簡(jiǎn)單的可視化界面來(lái)顯示數據庫信息。

如果您熟悉數據庫的強大功能,就會(huì )認識到SQL語(yǔ)言可使您執行比我們此處所述操作更強大的任務(wù)。例如,您可以創(chuàng )建新表、添加、更改或刪除表的行、列或單個(gè)表元。使用JDBC,所有這一切都變得通用和易于處理。

如果您使用的是特定平臺的數據庫驅動(dòng)程序,如JDBC-ODBCBridge,則您在編寫(xiě)應用程序時(shí)會(huì )受到限制,因為applet不能連接在另一臺計算機上運行的這個(gè)橋。其他客戶(hù)機-服務(wù)器數據庫,如IBM的DB2,允許您使用applet中的JDBC與其連接。



關(guān)于作者

 

IBM has authored this article

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Java的數據庫連接編程(JDBC)技術(shù)
JSP漸進(jìn)學(xué)習教程9
jdbc
《Java Web 應用程序設計立體化教程》第5章數據庫訪(fǎng)問(wèn)技術(shù)
JDBC 學(xué)習筆記1
Java連接Oracle數據庫
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久