JDBC的那些事兒!(2)
連接數(shù)據(jù)庫(kù)
所有與數(shù)據(jù)庫(kù)有關(guān)的對(duì)象和方法都在 java.sql 包中,因此在使用 JDBC 的程序中必須加入 "import java.sql.* "。 JDBC 要連接 ODBC 數(shù)據(jù)庫(kù),您必須首先加載 JDBC-ODBC 橋驅(qū)動(dòng)程序
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
該語(yǔ)句加載驅(qū)動(dòng)程序,并創(chuàng)建該類的一個(gè)實(shí)例。然后,要連接一個(gè)特定的數(shù)據(jù)庫(kù),您必須創(chuàng)建 Connect 類的一個(gè)實(shí)例,并使用 URL 語(yǔ)法連接數(shù)據(jù)庫(kù)。
String url = "jdbc:odbc:Grocery prices";
Connection con = DriverManager.getConnection(url);
請(qǐng)注意,您使用的數(shù)據(jù)庫(kù)名是您在 ODBC 設(shè)置面板中輸入的“數(shù)據(jù)源”名稱。
URL 語(yǔ)法可能因數(shù)據(jù)庫(kù)類型的不同而變化極大。
jdbc:subprotocol:subname
第一組字符代表連接協(xié)議,并且始終是 jdbc。還可能有一個(gè)子協(xié)議,在此處,子協(xié)議被指定為 odbc。它規(guī)定了一類數(shù)據(jù)庫(kù)的連通性機(jī)制。如果您要連接其它機(jī)器上的數(shù)據(jù)庫(kù)服務(wù)器,可能也要指定該機(jī)器和一個(gè)子目錄:
jdbc:bark//doggie/elliott
最后,您可能要指定用戶名和口令,作為連接字符串的一部分:
jdbc:bark//doggie/elliot;UID=GoodDog;PWD=woof
*******************************************************************************************
*******************************************************************************************
上面給出了連接數(shù)據(jù)庫(kù)的一種方法,其實(shí)還有另外一種方法,如下:
System.setProperty("jdbc.drivers","sun.jdbc.odbc.JdbcOdbcDriver");
String url = "jdbc:odbc:Grocery prices";
Connection con=DriverManager.getConnection(url);
說(shuō)明:
我們可以用System.getProperty("jdbc.drivers")對(duì)設(shè)定的System屬性值進(jìn)行查詢。其實(shí),對(duì)于System屬性,系統(tǒng)認(rèn)可的屬性如下:
java.version Java Runtime Environment version
java.vendor Java Runtime Environment vendor
java.vendor.url Java vendor URL
java.home Java installation directory
java.vm.specification.version Java Virtual Machine specification version
java.vm.specification.vendor Java Virtual Machine specification vendor
java.vm.specification.name Java Virtual Machine specification name
java.vm.version Java Virtual Machine implementation version
java.vm.vendor Java Virtual Machine implementation vendor
java.vm.name Java Virtual Machine implementation name
java.specification.version Java Runtime Environment specification version
java.specification.vendor Java Runtime Environment specification vendor
java.specification.name Java Runtime Environment specification name
java.class.version Java class format version number
java.class.path Java class path
java.library.path List of paths to search when loading libraries
java.io.tmpdir Default temp file path
java.compiler Name of JIT compiler to use
java.ext.dirs Path of extension directory or directories
os.name Operating system name
os.arch Operating system architecture
os.version Operating system version
file.separator File separator ("/" on UNIX)
path.separator Path separator (":" on UNIX)
line.separator Line separator ("\n" on UNIX)
user.name User's account name
user.home User's home directory
user.dir User's current working directory
大家可以看到其中并沒有jdbc.drivers這一個(gè)屬性,但是System的屬性可以隨意的由我們來(lái)添加,比如我們用setProperty設(shè)定了一個(gè)名為“bacoo”的屬性,并指定該屬性值為“test”的話,那么當(dāng)我們用getProperty時(shí)就可以檢索到屬性bacoo的值為test。這里之所以要加入“jdbc.drivers”這個(gè)屬性值,是因?yàn)镈riverManager這個(gè)類默認(rèn)的會(huì)在初始化時(shí)去System中搜索這一屬性的值,在這個(gè)屬性值中我們可以將多個(gè)需要加載的驅(qū)動(dòng)用冒號(hào)“:”隔開,又由于DriverManager是一個(gè)靜態(tài)類(其實(shí)在定義一個(gè)類時(shí),不允許用static修飾,只允許public、final、abstract三個(gè)修飾符,這里說(shuō)其是靜態(tài)類指的是該類的所有方法和屬性<其實(shí)該類也沒有屬性,連構(gòu)造函數(shù)都沒有>均是靜態(tài)的),因此在調(diào)用DriverManager.getConnection(url)時(shí),DriverManager需要先初始化,就會(huì)加載驅(qū)動(dòng)了。
訪問數(shù)據(jù)庫(kù)
一旦連接到數(shù)據(jù)庫(kù),就可以請(qǐng)求表名以及表列的名稱和內(nèi)容等信息,而且您可以運(yùn)行 SQL 語(yǔ)句來(lái)查詢數(shù)據(jù)庫(kù)或者添加或修改其內(nèi)容。可用來(lái)從數(shù)據(jù)庫(kù)中獲取信息的對(duì)象有:
DatabaseMetaData
有關(guān)整個(gè)數(shù)據(jù)庫(kù)的信息:表名、表的索引、數(shù)據(jù)庫(kù)產(chǎn)品的名稱和版本、數(shù)據(jù)庫(kù)支持的操作。
DatabaseMetaData dbmd;
dbmd=con.getMetaData();
下面重點(diǎn)介紹一下DatabaseMetaDat中的兩個(gè)重要函數(shù)getTables和getColumns:
ResultSet
getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types)
僅返回與目錄、模式、表名稱和(表)類型標(biāo)準(zhǔn)匹配的表描述。
catalog:要在其中查找表名的目錄名。對(duì)于 JDBC-ODBC 數(shù)據(jù)庫(kù)以及許多其他數(shù)據(jù)庫(kù)而言,可將其設(shè)置為 null。這些數(shù)據(jù)庫(kù)的目錄項(xiàng)實(shí)際上是它在文件系統(tǒng)中的絕對(duì)路徑名稱。
schemaPattern:要包括的數(shù)據(jù)庫(kù)“方案”。許多數(shù)據(jù)庫(kù)不支持方案,而對(duì)另一些數(shù)據(jù)庫(kù)而言,它代表數(shù)據(jù)庫(kù)所有者的用戶名。一般將它設(shè)置為 null。
tableNamePattern:一個(gè)掩碼,用來(lái)描述您要檢索的表的名稱。如果您希望檢索所有表名,則將其設(shè)為通配符 %。請(qǐng)注意,SQL 中的通配符是 % 符號(hào),而不是一般 PC 用戶的 * 符號(hào)。
types[]:這是描述您要檢索的表的類型的 String 數(shù)組。數(shù)據(jù)庫(kù)中通常包括許多用于內(nèi)部處理的表,而對(duì)作為用戶的您沒什么價(jià)值。如果它是空值,則您會(huì)得到所有這些表。如果您將其設(shè)為包含字符串“TABLES”的單元素?cái)?shù)組,您將僅獲得對(duì)用戶有用的表格。
例子:
String [] types=new String[1];
types[0]="TABLE";
rs=dbmd.getTables(null, null, "%", types);
Java Doc中說(shuō)該函數(shù)返回的表描述信息都包括以下10種信息,TABLE_CAT、TABLE_SCHEM、TABLE_NAME、TABLE_TYPE、REMARKS、TYPE_CAT、TYPE_SCHEM、TYPE_NAME、SELF_REFERENCING_COL_NAME、REF_GENERATION,但是在實(shí)際測(cè)試時(shí),返回的結(jié)果中只有TABLE_CAT、TABLE_SCHEM、TABLE_NAME、TABLE_TYPE、REMARKS這5項(xiàng)。順便要說(shuō)一聲的是,變量types可以取的值有:"TABLE"、"VIEW"、"SYSTEM TABLE"、"GLOBAL TEMPORARY"、"LOCAL TEMPORARY"、"ALIAS" 和 "SYNONYM",通常只取TABLE。
*************************************************************************************************************************************************************************************************
ResultSet
getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
僅返回與目錄、模式、表和列名稱標(biāo)準(zhǔn)匹配的列描述。
通常在得到有關(guān)指定表(比如我們這里指定了表名為FoodPrice)的列的描述信息的結(jié)果集(rs)之后,我們重點(diǎn)關(guān)心的是COLUMN_NAME、DATA_TYPE(數(shù)據(jù)類型占用的字節(jié)數(shù),比如整型就是4)、TYPE_NAME(INTEGER、CURRENCY之類的類型名稱),當(dāng)然最關(guān)心的肯定是COLUMN_NAME了。下面把結(jié)果集中所有可以得到的信息列給出如下:
TABLE_CAT、TABLE_SCHEM、TABLE_NAME、COLUMN_NAME、DATA_TYPE、TYPE_NAME、COLUMN_SIZE、BUFFER_LENGTH、DECIMAL_DIGITS、NUM_PREC_RADIX、NULLABLE、REMARKS、COLUMN_DEF、SQL_DATA_TYPE、SQL_DATETIME_SUB、CHAR_OCTET_LENGTH、ORDINAL_POSITION、IS_NULLABLE、ORDINAL。
例子:
rs=dbmd.getColumns(null, null, "FoodPrice", null);
因此我們通常用
while(rs.next()){
System.out.print(rs.getString("COLUMN_NAME")+"\t");
}來(lái)得到該表中所有的列名稱。其實(shí)這就是一個(gè)從結(jié)果集中檢索的結(jié)果。
ResultSet
關(guān)于某個(gè)表的信息或一個(gè)查詢的結(jié)果。您必須逐行訪問數(shù)據(jù)行,但是您可以任何順序訪問列。
對(duì)于數(shù)據(jù)庫(kù)中表的描述信息的結(jié)果集可以這樣得到:rs=dbmd.getTables(null, null, "%", null);
對(duì)于某張表中的列的描述信息的結(jié)果集可以這樣得到:rs=dbmd.getColumns(null, null, "FoodPrice", null);
對(duì)于要從表中檢索具體的符合要求的結(jié)果集(而不僅僅是一些描述信息了)就必須使用如下的方法:
Statement st=con.createStatement();
String query="SELECT FoodName FROM FOOD;";//注意字符串中要包含“;”!
rs=st.executeQuery(query);
ResultSetMetaData
有關(guān) ResultSet 中列的名稱和類型的信息。
ResultSetMetaData rsmd;
rsmd = rs.getMetaData();
numCols = rsmd.getColumnCount();
// 打印列名
for (i = 1; i <= numCols; i++)
System.out.print(rsmd.getColumnName(i) + " ");
System.out.println();
最后,給出一些零散的知識(shí):
(1)對(duì)于數(shù)據(jù)庫(kù)的連接、訪問等等操作都需要放在try和catch塊中進(jìn)行,都有可能拋出SQLException異常,使用該異常類需要import java.sql.*;
(2)前面提到的DatabaseMetaDat、ResultSet、ResultSetMetaData均是接口,而不是類,在下面的例子中,通過(guò)跟蹤調(diào)試,可以發(fā)現(xiàn)在程序運(yùn)行過(guò)程中產(chǎn)生的都是基于JdbcOdbc驅(qū)動(dòng)的類,即JdbcOdbcResultSet等類,把這些類(它們都實(shí)現(xiàn)了相應(yīng)的接口)實(shí)例化后賦值給ResultSet接口,如ResultSet rs=dbmd.getColumns(null, null, "FoodPrice", null);因此,我們們不難推斷出對(duì)于其他類型的數(shù)據(jù)庫(kù)驅(qū)動(dòng),均是這樣一個(gè)原理,同時(shí)也理解了為什么Java中有許多接口,而并沒有與這些接口對(duì)應(yīng)的實(shí)現(xiàn)了它們的類,再一次驗(yàn)證了接口就是一種標(biāo)準(zhǔn),一種規(guī)范。
給出一個(gè)完整的例子:
package com.bacoo.www;
import java.sql.*;
public class JdbcOdbcTest {
ResultSet rs;
ResultSetMetaData rsmd;
DatabaseMetaData dbmd;
Connection con;
int numCols,i;
public JdbcOdbcTest(){
System.setProperty("jdbc.drivers","sun.jdbc.odbc.JdbcOdbcDriver");
String url="jdbc:odbc:Groceries";
String query="SELECT DISTINCTROW FoodName FROM Food " +
"WHERE (FoodName like 'C%');";
try{
//Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con=DriverManager.getConnection(url);
dbmd=con.getMetaData();
System.out.println("Connected to:"+dbmd.getURL());
System.out.println("Driver "+ dbmd.getDriverName());
String [] types=new String[1];
types[0]="TABLE";
rs=dbmd.getTables(null, null, "%", null);
dumpResults("--Tables--");
rs.close();
}catch(Exception e){
System.out.println(e);
}
System.out.println("--Column Names--");
try{
rs=dbmd.getColumns(null, null, "FoodPrice", null);
while(rs.next()){
System.out.print(rs.getString("COLUMN_NAME")+" ");
}
System.out.println();
rs.close();
}catch(Exception e){
System.out.println(e);
}
try{
Statement st=con.createStatement();
rs=st.executeQuery("SELECT FoodName FROM FOOD;");
}catch(Exception e){
System.out.println("query exception");
}
dumpResults("--contents of FoodName column--");
try{
Statement st=con.createStatement();
rs=st.executeQuery(query);
}catch(Exception e){
System.out.println("query exception");
}
dumpResults("--Results of Query--");
}
private void dumpResults(String head) {
// 這是打印列標(biāo)頭和每列的內(nèi)容的
// 通用方法
System.out.println(head);
try {
// 從元數(shù)據(jù)中獲取列數(shù)
rsmd = rs.getMetaData();
numCols = rsmd.getColumnCount();
// 打印列名
for (i = 1; i <= numCols; i++)
System.out.print(rsmd.getColumnName(i) + "、");
System.out.println();
// 打印列內(nèi)容
while (rs.next()) {
for (i = 1; i <= numCols; i++)
System.out.print(rs.getString(i) + "\t");
System.out.println();
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
new JdbcOdbcTest();
System.out.println(System.getProperty("jdbc.drivers"));
}
}
運(yùn)行的結(jié)果是:
Connected to:jdbc:odbc:Groceries
Driver JDBC-ODBC Bridge (odbcjt32.dll)
--Tables--
TABLE_CAT、TABLE_SCHEM、TABLE_NAME、TABLE_TYPE、REMARKS、
C:\Documents and Settings\Administrator\桌面\db1 null MSysAccessObjects SYSTEM TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null MSysAccessXML SYSTEM TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null MSysACEs SYSTEM TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null MSysObjects SYSTEM TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null MSysQueries SYSTEM TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null MSysRelationships SYSTEM TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null Food TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null FoodPrice TABLE null
C:\Documents and Settings\Administrator\桌面\db1 null Stores TABLE null
--Column Names--
FSKey StoreKey FoodKey Price
--contents of FoodName column--
FoodName、
Apples
Oranges
Hamburger
Butter
Milk
Coca Cola
Green beans
--Results of Query--
FoodName、
Coca Cola
sun.jdbc.odbc.JdbcOdbcDriver
當(dāng)然使用該例子,必須要先建立一個(gè)數(shù)據(jù)源。
posted on 2007-12-20 23:47 so true 閱讀(843) 評(píng)論(0) 編輯 收藏 所屬分類: Java