Java 實 作 與 應 用
( 十 六 ) ----- Java和 資 料 庫 互 動 的 內 幕 大 公 開 |
---|
Java電 腦 語 言 和 資 料 庫 管 理 系 統 結 合 起 來 , 才 能 使 Java在 大 型 應 用 程 式 系 統 之 中 擔 當 重 任 。 本 文 介 紹 聯 接 資 料 庫 的 JDBC規 範 的 原 理 、 架 構 、 應 用 程 式 介 面 和 驅 動 程 式 等 , 並 以 測 試 工 具 實 例 來 介 紹 Java寫 碼 的 方 式 。 |
前 言
Java和 資 料 庫 相 通 的 介 面 JDBC是 最 新 流 行 Web電 腦 技 術 的 幕 後 大 功 臣 。 本 文 用 一 個 簡 單 的 供 應 商 管 理 系 統 實 例 來 說 明 如 何 用 JDBC來 做 資 料 庫 紀 錄 的 建 立 、 更 新 、 刪 除 和 查 詢 等 工 作 , 並 且 介 紹 一 些 JDBC程 式 設 計 的 內 幕 。
在 美 國 , 一 個 嶄 新 的 電 腦 運 算 紀 元 已 經 來 臨 了 , 以 全 球 資 訊 網 的 Web技 術 已 然 來 勢 洶 洶 地 欲 取 代 傳 統 式 的 主 從 運 算 環 境 。 新 的 網 路 運 算 架 構 除 了 應 用 開 放 式 的 Internet網 路 通 訊 基 本 建 設 之 外 , 最 主 要 的 是 利 用 Java的 跨 越 平 台 特 性 , 使 得 它 不 論 在 技 術 理 論 或 在 實 務 上 , 都 比 主 從 運 算 架 構 要 強 得 很 多 。
Web技 術 的 幕 後 功 臣
以 Internet上 Web的 技 術 發 展 史 來 看 , 整 個 技 術 的 發 展 真 是 可 以 用 一 日 千 里 來 形 容 。 當 兩 三 年 前 , Internet的 第 一 波 浪 潮 剛 剛 興 起 時 , 瀏 覽 器 和 靜 態 的 HTML是 當 時 的 主 流 派 , 人 們 只 要 能 利 用 瀏 覽 器 在 彈 指 間 造 訪 網 路 上 的 任 一 個 網 站 , 達 到 古 人 所 說 的 「 觀 古 今 於 須 臾 , 撫 四 海 於 一 瞬 」 的 境 界 , 就 非 常 滿 足 了 。
可 是 過 不 了 多 久 , 人 們 又 發 現 光 只 是 在 網 路 上 遊 覽 , 日 子 久 了 對 那 些 靜 態 的 畫 面 就 失 去 了 新 鮮 感 了 , 為 什 麼 不 能 利 用 Internet來 作 一 些 資 料 處 理 的 工 作 呢 ? 於 是 表 格 式 的 HTML及 用 CGI和 資 料 庫 聯 絡 的 電 腦 技 術 就 應 運 而 生 , 這 可 以 讓 程 式 設 計 師 用 來 做 一 些 有 限 度 的 程 式 應 用 , 讓 Internet可 以 作 一 些 簡 單 的 網 路 應 用 程 式 。
就 在 表 格 式 HTML和 CGI等 技 術 開 始 派 上 用 途 的 同 時 , Java電 腦 技 術 異 軍 突 起 地 進 入 了 Web的 電 腦 技 術 群 中 。 由 於 Java是 一 個 純 物 件 導 向 的 語 言 , 又 有 平 台 獨 立 的 特 性 , 所 以 馬 上 就 取 代 了 其 他 的 程 式 設 計 方 法 , 成 為 全 球 資 訊 網 上 程 式 設 計 語 言 的 主 流 派 。
現 在 人 們 對 Internet的 要 求 , 早 已 超 過 了 簡 單 靜 態 的 HTML畫 面 , 例 如 那 些 動 態 的 HTML、 大 型 的 網 路 應 用 程 式 和 在 Intranet及 Extranet上 面 的 程 式 應 用 才 是 真 正 在 網 路 上 迫 切 需 要 的 。 這 就 好 像 過 去 是 在 高 速 公 路 上 遊 覽 就 可 以 滿 足 了 , 現 在 則 要 研 究 從 高 速 公 路 所 到 的 目 的 地 能 夠 提 供 怎 麼 樣 的 服 務 和 可 以 獲 得 什 麼 特 殊 的 產 品 才 能 滿 足 需 求 。
而 想 讓 在 Internet上 面 遊 覽 的 人 能 夠 「 聞 香 下 馬 , 知 味 停 車 」 的 話 , 一 定 要 借 重 Java的 電 腦 技 術 , 尤 其 是 Java和 資 料 庫 聯 結 的 JDBC技 術 , 更 是 整 個 Web技 術 的 核 心 。 目 前 在 Internet上 面 , 將 網 路 通 訊 技 術 加 上 Java的 跨 越 平 台 特 性 和 JDBC資 料 庫 的 功 能 , 是 開 發 大 型 重 要 任 務 網 路 應 用 程 式 的 最 佳 解 決 方 案 , 靠 JDBC這 個 幕 後 大 功 臣 會 使 Web 電 腦 技 術 更 為 走 紅 。
筆 者 在 上 一 期 的 本 欄 之 中 , 已 經 將 JDBC的 架 構 和 概 念 作 了 一 番 介 紹 , 現 在 筆 者 要 以 一 些 實 際 的 程 式 範 例 來 說 明 各 種 SQL指 述 的 程 式 設 計 方 法 , 並 用 這 些 程 式 組 合 成 為 一 個 供 應 商 管 理 系 統 。
供 應 商 管 理 系 統
供 應 商 ( Vendor) 是 指 在 一 個 公 司 中 外 界 各 種 器 材 或 是 材 料 的 供 應 廠 商 , 例 如 一 個 公 司 之 中 所 用 的 各 種 軟 體 可 能 是 分 別 向 各 個 不 同 的 軟 體 公 司 去 購 買 的 , 諸 如 IBM、 微 軟 、 網 景 、 網 威 、 甲 骨 文 、 寶 蘭 、 昇 陽 等 等 公 司 都 是 軟 體 的 供 應 商 。 此 外 , 電 腦 的 硬 體 、 通 訊 器 材 和 其 他 設 備 都 有 不 同 的 供 應 廠 商 。
筆 者 最 近 在 公 司 之 中 執 行 一 個 公 元 兩 千 年 的 專 案 計 劃 , 以 確 定 有 關 網 路 管 理 系 統 之 中 的 所 有 軟 體 、 硬 體 和 網 路 通 訊 器 材 都 能 在 公 元 兩 千 年 還 能 正 常 運 轉 。 我 所 作 的 第 一 件 事 就 是 將 所 有 網 路 管 理 工 具 的 供 應 商 作 一 個 庫 存 整 理 , 這 時 一 個 供 應 商 的 管 理 系 統 就 非 常 需 要 。
又 例 如 想 要 將 公 司 中 所 有 供 應 商 建 檔 管 理 , 隨 時 可 以 找 到 相 關 廠 商 的 網 站 位 址 或 是 聯 絡 電 話 時 , 一 個 供 應 商 的 管 理 系 統 也 是 必 要 的 。 為 了 簡 化 我 們 這 個 JDBC的 程 式 範 例 , 在 這 個 供 應 商 的 資 料 庫 表 格 之 中 只 放 了 五 個 資 料 元 件 , 分 別 是 :
● 供 應 商 的 識 別 號 碼 ( vendorID) , 一 個 整 數 值 用 來 代 表 整 筆 紀 錄 。
● 供 應 商 名 字 ( vendorName) , 一 組 字 串 廠 商 名 稱 。
● 供 應 商 的 電 話 號 碼 ( vendorPhoneNo) , 為 了 簡 化 起 見 , 用 字 串 來 代 表 電 話 號 碼 。
● 供 應 商 的 網 址 ( vendo URL) , 用 字 串 來 代 表 供 應 商 的 網 站 的 URL網 址 。
● 供 應 商 的 型 別 ( vendorType) , 以 整 數 值 來 儲 存 供 應 商 的 型 別 , 例 如 硬 體 商 、 軟 體 商 、 通 訊 器 材 廠 商 、 材 料 供 應 商 等 等 不 同 的 類 別 。
圖 一
在 供 應 商 管 理 系 統 上 , 首 先 我 們 要 有 一 個 供 應 商 的 類 別 , 其 次 要 有 一 個 類 別 專 門 來 處 理 供 應 商 物 件 和 資 料 庫 交 通 的 各 種 相 關 事 宜 , 最 後 則 要 有 一 些 類 別 和 使 用 者 溝 通 。 如 圖 一 所 示 , 我 們 這 個 供 應 商 管 理 系 統 除 了 資 料 庫 之 外 , 有 下 面 的 三 種 類 別 :
管 理 系 統 的 類 別 設 計
在 上 面 的 資 料 型 態 設 計 之 中 , 比 較 特 別 的 是 URL。 在 理 論 上 Java有 URL這 種 物 件 , 照 理 說 應 該 用 URL來 放 置 供 應 商 的 網 址 。 不 過 , 在 資 料 庫 之 中 並 沒 有 URL這 一 種 型 態 , 而 且 在 JDBC之 中 也 沒 有 對 應 的 設 置 和 擷 取 的 方 法 , Java有 一 些 類 別 對 URL也 不 支 援 , 故 改 用 字 串 的 資 料 比 較 方 便 。
Vendor類 別 : 主 要 是 定 義 一 個 供 應 商 的 物 件 , 並 且 將 一 些 和 物 件 之 中 資 料 元 件 處 理 的 相 關 方 法 放 在 這 一 個 類 別 之 中 。
VendorDBManager類 別 : 是 Vendor物 件 和 資 料 庫 溝 通 時 的 各 種 方 法 的 集 中 類 別 。 它 含 有 將 資 料 庫 聯 結 打 開 或 關 閉 的 方 法 , 以 及 用 SQL去 建 置 、 更 新 、 查 詢 和 刪 除 資 料 庫 之 中 供 應 商 紀 錄 的 各 種 方 法 。
圖 二
Vendor UI類 別 或 是 Vendor Test類 別 : 含 有 各 種 人 機 介 面 及 測 試 的 驅 動 程 式 , 用 來 管 理 或 是 測 試 供 應 商 之 類 的 各 種 程 式 及 方 法 。
除 了 上 面 的 三 種 類 別 之 外 , 我 們 還 用 了 一 些 SQL的 指 令 來 建 置 資 料 庫 之 中 的 表 格 。 當 然 , 在 很 多 資 料 管 理 系 統 之 中 , 可 以 直 接 利 用 系 統 的 介 面 來 建 置 資 料 庫 之 中 的 供 應 商 表 格 , 例 如 圖 二 就 是 在 微 軟 的 SQLServer 6.5之 下 , 利 用 圖 形 操 作 介 面 來 建 置 供 應 商 的 表 格 。 不 過 , 如 果 資 料 欄 位 很 多 , 而 且 要 應 用 到 其 他 的 資 料 庫 系 統 上 面 時 , 利 用 圖 形 介 面 就 很 不 方 便 , 因 此 要 將 建 立 供 應 商 的 SQL指 述 放 在 一 個 程 式 檔 案 之 中 , 如 下 面 的 程 式 碼 :
DROP TABLE vendor
GO
CREATE TABLE vendor (
vendorId int NOT NULL ,
vendorName varchar (64) NOT NULL ,
vendorPhoneNo varchar (15) NULL ,
vendorURL varchar (128) NULL ,
vendorType int NOT NULL ,
CONSTRAINT PK_vendor_1__10 PRIMARY KEY CLUSTERED
(
vendorId
),
CONSTRAINT UQ_vendor_2__10 UNIQUE NONCLUSTERED
(
vendorId
),
CONSTRAINT UQ_vendor_3__10 UNIQUE NONCLUSTERED
(
vendorName
)
)
GO
在 SQLServer之 中 , 帶 有 SQL程 式 的 產 生 器 , 如 圖 三 所 示 , 透 過 圖 形 使 用 介 面 也 可 以 產 生 SQL 的 程 式 。
圖 三
從 上 面 的 SQL程 式 中 可 看 出 , 整 數 有 對 應 的 資 料 型 態 , 而 字 串 在 Java之 中 是 可 以 有 任 何 的 長 度 , 但 在 資 料 庫 之 中 卻 得 預 先 設 定 最 大 的 長 度 , 以 可 變 長 字 串 ( varchar) 的 方 式 去 建 置 。
供 應 商 的 類 別
在 Vendor類 別 中 主 要 有 三 大 部 份 , 分 別 是 物 件 中 各 個 資 料 元 件 屬 性 的 定 義 、 建 構 函 式 方 法 和 一 些 擷 取 和 設 定 資 料 元 件 屬 性 的 方 法 。 Vendor紀 錄 內 的 五 個 資 料 元 件 , 在 類 別 之 中 都 是 採 用 private 的 方 法 去 定 義 的 , 這 是 物 件 導 向 中 常 用 的 封 包 原 理 , 將 物 件 之 中 的 變 數 隱 藏 起 來 , 不 讓 外 界 其 他 的 類 別 任 意 改 動 物 件 之 中 的 變 數 。
在 建 構 函 式 方 法 之 中 , 我 們 一 共 寫 了 三 個 不 同 的 方 法 , 分 別 用 來 建 立 一 個 空 的 供 應 商 物 件 以 供 使 用 者 填 入 相 關 的 資 料 ; 或 是 建 立 一 個 基 本 的 物 件 以 便 用 來 到 資 料 庫 中 更 新 資 料 ; 抑 或 是 一 個 全 部 五 個 資 料 元 件 的 物 件 用 來 作 為 和 資 料 庫 中 紀 錄 相 互 轉 換 之 用 。
其 次 , 在 資 料 的 擷 取 和 設 定 方 面 , 每 一 個 私 有 的 資 料 元 件 都 得 要 有 相 對 應 的 set和 get的 方 法 , 如 此 才 能 在 改 動 類 別 內 部 資 料 名 稱 時 , 其 他 外 界 的 程 式 不 會 受 到 影 響 。
最 後 , 又 加 上 toString( ) 和 _display( ) 兩 個 方 法 , 這 是 為 了 程 式 的 除 錯 及 測 試 而 設 立 的 。 整 個 供 應 商 類 別 的 程 式 全 文 如 下 :
/**
* This class defines all data elements within a vendor able.
*
*
* * * * p$ $
* The major properties include the following:
* * * * pre$ $
*
* * * * h3$ $ PROPERTIES* * * /h3$ $
*
* vendorId
* vendorName
* vendorphoneNo
* vendorURL
* vendorType
*
* * * * /pre$ $
*
* @author Symon Chang
* @version 1.0.0, 05-10-97 SC New created for Hopenet
* @see VendorDBManager
*/
public class Vendor
{
/**
* Vendor ID
*/
private int vendorId;
/**
* Vendor name
*/
private String vendorName;
/**
* Vendor Phone
*/
private String vendorPhoneNo;
/**
* Vendor URL
*/
private String vendorURL;
/**
* Vendor type value: Software Vendor
*/
public static final int SOFTWAREVENDOR = 2;
/**
* Vendor type value: Hardware Vendor
*/
public static final int HARDWAREVENDOR = 4;
/**
* Vendor type value: Telecomm Vendor
*/
public static final int TELECOMMVENDOR = 8;
/**
* Vendor Type.
*/
private int vendorType;
/**
* Create a default vendor object for update.
*/
public Vendor (
String inputVendorName,
String inputVendorPhoneNo,
String inputVendorURL )
{
vendorId = 0;
vendorName = inputVendorName;
vendorPhoneNo= inputVendorPhoneNo;
vendorURL = inputVendorURL;
vendorType = 0;
}
/**
* Create a Vendor object.
*/
public Vendor (
int inputVendorId,
String inputVendorName,
String inputVendorPhoneNo,
String inputVendorURL,
int inputVendorType)
{
vendorId = inputVendorId;
vendorName = inputVendorName;
vendorPhoneNo= inputVendorPhoneNo;
vendorURL = inputVendorURL;
vendorType = inputVendorType;
}
/**
* Create an empty vendor object.
*/
public Vendor ()
{
vendorId = 0;
vendorName = “ ” ;
vendorPhoneNo = “ ” ;
vendorURL = “ ” ;
vendorType = 0;
}
/**
* Return the property from the object.
* @return vendorId value of the property.
*/
public int getVendorId()
{
return vendorId;
}
/**
* Return the property from the object.
* @return vendorName value of the property.
*/
public String getVendorName()
{
return vendorName;
}
/**
* Return the property from the object.
* @return phoneNumber value of the property.
*/
public String getVendorPhoneNo()
{
return vendorPhoneNo;
}
/**
* Return the property from the object.
* @return VendorURL value of the property.
*/
public String getVendorURL()
{
return vendorURL;
}
/**
* Return the property from the object.
* @return VendorType value of the property.
*/
public int getVendorType()
{
return vendorType;
}
/**
* Put a property of vendor ID into the object.
* @param inVendorId value to be set
*/
public void setVendorId(int inVendorId )
{
vendorId = inVendorId;
}
/**
* Put a property of vendor name into the object.
* @param name value to be set
*/
public void setVendorName(String inVendorName )
{
vendorName = inVendorName;
}
/**
* Put a property into the object.
* @param phoneNumber value to be set
*/
public void setVendorPhoneNo(String inVendorPhoneNo )
{
vendorPhoneNo = inVendorPhoneNo;
}
/**
* Put a property into the object.
* @param inVendorURL value to be set
*/
public void setVendorURL(String inVendorURL )
{
vendorURL = inVendorURL;
}
/**
* Put a property into the object.
* @param inVendorType value to be set
*/
public void setVendorType(int inVendorType )
{
vendorType= inVendorType;
}
/**
* Return a String of the vendor object.
* @return Vendor object
*/
public String toString()
{
return ( vendorId + “ “ + vendorName +
“ Phone: “ + vendorPhoneNo +
“ URL: “ + vendorURL +
“ Type: “ + vendorType);
}
/**
* dsiplay the vendor object for debugging.
*/
public void _display()
{
System.out.println (“ Vendor Id : “ + vendorId +
“ \n Name : “ + vendorName +
“ \n Phone Number: “ + vendorPhoneNo +
“ \n URL : “ + vendorURL +
“ \n Type : “ + vendorType);
}
}
在 上 面 的 這 個 原 始 程 式 碼 之 中 , 放 了 很 多 特 別 的 註 解 格 式 , 這 是 Java的 特 有 方 式 。
用 這 種 方 式 所 寫 出 來 的 Java程 式 , 可 以 利 用 Java現 成 的 工 具 javadoc去 產 生 成 HTML格 式 的 程 式 說 明 文 件 , 如 圖 四 所 示 。 在 使 用 這 種 註 解 方 式 時 , 要 特 別 注 意 在 *和 @符 號 之 間 , 只 能 有 一 格 空 白 , 如 果 多 於 一 格 空 白 就 不 會 產 生 應 有 的 效 果 。
圖 四
從 Vendor類 別 的 原 始 程 式 碼 上 可 以 看 出 , 每 一 個 資 料 元 件 對 應 地 會 需 要 三 、 四 十 條 的 程 式 碼 。 當 類 別 之 中 的 資 料 元 件 數 目 很 多 時 , 這 種 重 複 的 寫 碼 方 式 就 會 變 得 很 花 時 間 , 而 且 在 實 質 上 並 沒 有 很 多 複 雜 的 邏 輯 。 針 對 這 一 點 , 最 近 新 推 出 的 Java 程 式 開 發 工 具 之 中 , 就 有 些 可 以 幫 助 程 式 設 計 師 來 自 動 地 產 生 上 面 的 這 些 程 式 碼 , 以 免 除 冗 長 輸 入 的 困 苦 。 例 如 IBM所 推 出 的 VisalAge for Java程 式 開 發 工 具 上 , 就 有 這 種 程 式 產 生 器 的 功 能 。
讀 者 或 許 會 問 , 為 什 麼 要 這 麼 麻 煩 ? 如 果 把 所 有 的 資 料 元 件 都 改 成 public的 資 料 型 態 , 整 個 Vendor的 類 別 可 能 在 不 到 二 十 條 程 式 碼 之 內 就 可 以 完 成 , 而 且 也 可 以 達 到 相 同 的 功 效 。 為 什 麼 要 寫 那 麼 多 的 程 式 來 做 這 麼 簡 單 的 事 呢 ?
如 果 是 一 個 程 式 設 計 師 , 或 是 學 校 的 學 生 自 己 寫 一 些 Java的 程 式 來 玩 一 玩 , 用 一 些 簡 單 的 捷 徑 也 是 無 可 厚 非 的 , 但 是 對 於 一 個 大 型 的 程 式 開 發 計 劃 , 同 時 有 很 多 程 式 設 計 師 在 一 起 工 作 , 又 要 考 慮 到 日 後 程 式 維 護 和 保 養 的 問 題 時 , 就 得 依 照 物 件 導 向 程 式 設 計 的 規 矩 , 並 且 加 上 詳 細 的 程 式 文 件 說 明 , 以 免 等 到 程 式 寫 得 很 大 , 或 時 間 又 過 得 很 久 以 後 , 沒 有 人 能 弄 懂 程 式 的 來 龍 去 脈 , 而 造 成 無 法 改 進 和 保 養 的 困 境 。