Java的資料庫編程(JDBC)技術
第一節 JDBC概述
為什麼採用JDBC、JDBC基本程式結構、JDBC的缺點、JDBC的工作原理、JDBC的結構、資料庫應用的模型、通過JDBC 實現對資料庫的訪問
第二節 建立與資料來源的串連
JDBC驅動程式、串連的一般方法、Access的串連應用、SQL Server 2000的串連應用、MySQL的串連應用、Oracle的串連應用、DB2的串連應用、不同種類的資料庫驅動程式配置
第三節 運用JDBC進行資料庫操作
查詢資料庫的一些結構資訊、查詢資料庫中的資料、使用宏語句、使用預存程序、處理大二進位欄位
第四節 交易處理
為什麼要處理事務、無事務的情況、交易處理的執行個體
第五節 遊標操作
ResultSet對象、遊標操作的執行個體分析、更新資料庫、插入操作、刪除操作、大量操作
第一節 JDBC概述
JDBC(Java DataBase Connectivity,Java 資料庫連接技術)是Java訪問資料庫資源的標準,JDBC標準定義了一組Java API,允許我們寫出SQL語句,然後交給資料庫。
有了JDBC從而可以使Java程式員用Java語言來編寫完整的資料庫方面的應用程式。另外也可以操作儲存在多種不同的資料庫管理系統中的資料,而與資料庫管理系統中資料存放區格式無關。同時Java語言的與平台的無關性,不必在不同的系統平台下編寫不同的資料庫應用程式。
一、為什麼採用JDBC
JDBC可以說是最老的企業Java規範之一,最早的起草日期要追溯到1996年,JDBC與微軟開發的開放資料連線(Open Database Connectivity,ODBC)標準具有同樣的功能,它提供一組通用的API,通過資料庫特定的驅動程式來訪問資料庫。
如果沒有JDBC或者ODBC,開發人員必須使用不同的一組API來訪問不同的資料庫,而利用JDBC或者ODBC,則只需要使用一組API,再加上資料庫廠商提供的資料庫驅動程式就可以了。所以,利用JDBC,我們就可以把同一個企業級Java應用移植到另一個資料庫應用上。
JDBC設計的目的
1)ODBC:微軟的ODBC是用C編寫的,而且只適用於Windows平台,無法實現跨平台地操作資料庫。
2)SQL語言:SQL儘管包含有資料定義、資料操作、資料管理等功能,但它並不是一個完整的程式設計語言,而且不支援流量控制,需要與其它程式設計語言相配合使用。
3)JDBC的設計:由於Java語言具有健壯性、安全、易使用並自動下載到網路等方面的優點,因此如果採用Java語言來串連資料庫,將能克服ODBC局限於某一系統平台的缺陷;將SQL語言與Java語言相互結合起來,可以實現串連不同資料庫系統,即使用JDBC可以很容易地把SQL語句傳送到任何關係型資料庫中。
4)JDBC設計的目的:它是一種規範,設計出它的最主要的目的是讓各個資料庫開發商為Java程式員提供標準的資料庫訪問類和介面,使得獨立於DBMS的Java應用程式的開發成為可能(資料庫改變,驅動程式跟著改變,但應用程式不變)。
JDBC的主要功能:
1)建立與資料庫的串連;
2)發送SQL語句到任何關係型資料庫中;
3)處理資料並查詢結果。
二、JDBC基本程式結構
Try{
//(1)載入串連資料庫的驅動程式
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//(2)建立與資料庫的串連
Connection con=DriverManager.getConnection("jdbc:odbc:DatabaseDSN","Login","Password");
//(3)發送SQL語句到資料庫中
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery("select * from DBTableName");
//(4)處理資料並查詢結果。
while(rs.next()){
String name=rs.getString("Name") ;
int age=rs.getInt("age");
float wage=rs.getFloat("wage");
}
//(5)關閉
rs.close();
stmt.close();
con.close();
}catch(SQLException e){
System.out.println("SQLState:"+ e.getSQLState());
System.out.println("Message:" + e.getMessage());
System.out.println("Vendor:" + e.getErrorCode());
}
三、JDBC的缺點
1)JDBC並不符合物件導向的要求,JDBC要求你明確地處理資料欄位,並且將它們映射到關聯式資料庫的表中。開發人員被迫與兩種區別非常大的資料模型、語言和資料訪問手段打交道:Java,以及SQL中的關係資料模型。
2)在開發中實現從關係資料模型到Java物件模型的映射非常複雜,以致於多數開發人員從不為資料定義物件模型,而是簡單地編寫過程化的Java代碼來對底層的關聯式資料庫中的資料表進行操縱。
3)最終結果是:開發人員根本不能從物件導向的開發中得到任何好處。
四、JDBC的工作原理
JDBC 工作原理結構
Java的應用程式
JDBC API介面
JDBC 驅動程式管理器
JDBC 驅動程式
資料庫管理系統
JDBC的設計基於X/Open SQL CLI(調用級介面)這一模型。它通過定義出一組 API對象和方法以用於同資料庫進行互動。
在Java程式中要操作資料庫,一般應該通過如下幾步(利用JDBC訪問資料庫的編程步驟):
1)載入串連資料庫的驅動程式 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
2)建立與資料來源的串連
String url="jdbc:odbc:DatabaseDSN";
Connection con=DriverManager.getConnection(url,"Login","Password");
3)查詢資料庫:建立Statement對象並執行SQL語句以返回一個ResultSet對象。
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery("select * from DBTableName");
4)獲得目前記錄集中的某一記錄的各個欄位的值
String name=rs.getString("Name");
int age=rs.getInt("age");
float wage=rs.getFloat("wage");
5)關閉查詢語句及與資料庫的串連(注意關閉的順序先rs再stmt最後為con)
rs.close();
stmt.close();
con.close();
五、JDBC的結構
JDBC主要包含兩部分:面向Java程式員的JDBC API及面向資料庫廠商的JDBC Drive API。
1) 面向Java程式員的JDBC API:
Java程式員通過調用此API從而實現串連資料庫、執行SQL語句並返回結果集等編程資料庫的能力,它主要是由一系列的介面定義所構成。
java.sql.DriveManager:該介面主要定義了用來處理裝載驅動程式並且為建立新的資料庫連接提供支援。
java.sql.Connection:該介面主要定義了實現對某一種指定資料庫連接的功能。
java.sql.Statement:該介面主要定義了在一個給定的串連中作為SQL語句執行聲明的容器以實現對資料庫的操作。它主要包含有如下的兩種子類型。
java.sql.PreparedStatement:該介面主要定義了用於執行帶或不帶 IN 參數的先行編譯 SQL 陳述式。
java.sql.CallableStatement:該介面主要定義了用於執行資料庫的預存程序的雕用。
java.sql.ResultSet:該介面主要定義了用於執行對資料庫的操作所返回的結果集。
2) 面向資料庫廠商的JDBC Drive API:
(現在的資料庫廠商除了提供API介面之外,有一些廠商還提供了DBMS端的緩衝)
資料庫廠商必須提供相應的驅動程式並實現JDBC API所要求的基本介面(每個資料庫系統廠商必須提供對DriveManager、Connection、Statement、ResultSet等介面的具體實現),從而最終保證Java程式員通過JDBC實現對不同的資料庫操作。
六、資料庫應用的模型
1) 兩層結構(C/S):
在此模型下,用戶端的程式直接與資料庫伺服器相串連並發送SQL語句(但這時就需要在用戶端安裝被訪問的資料庫的JDBC驅動程式),DBMS伺服器向客戶返回相應的結果,客戶程式負責對資料的格式化。
client端 ODBC/JDBC Server端(DBMS)
主要的缺點:受資料庫廠商的限制,使用者更換資料庫時需要改寫客戶程式;受資料庫版本的限制,資料庫廠商一旦升級資料庫,使用該資料庫的客戶程式需要重新編譯和發布;對資料庫的操作與處理都是在客戶程式中實現,使客戶程式在編程與設計時較為複雜。
2) 三(或多)層結構(B/S):
在此模型下,主要在用戶端的程式與資料庫伺服器之間增加了一個中間伺服器(可以採用C++或Java語言來編程實現),隔離用戶端的程式與資料庫伺服器。用戶端的程式(可以簡單為通用的瀏覽器)與中間伺服器進行通訊,然後由中間伺服器處理用戶端程式的請求並管理與資料庫伺服器的串連。
七、通過JDBC 實現對資料庫的訪問
1)引用必要的包
import java.sql.*; //它包含有操作資料庫的各個類與介面
2)載入串連資料庫的驅動程式類
為實現與特定的資料庫相串連,JDBC必須載入相應的驅動程式類。這通常可以採用Class.forName()方法顯式地載入一個驅動程式類,由驅動程式負責向DriverManager登記註冊並在與資料庫相串連時,DriverManager將使用此驅動程式。
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
注意:
1.該條語句直接載入了sun公司提供的JDBC-ODBC Bridge驅動程式類。
2.ODBC-JDBC橋方式,可以採用ODBC資料來源名稱來指定資料庫檔案
String url="jdbc:odbc:studlist";
也可以直接採用指定資料庫檔案的物理位置(可以絕對路徑,也可以是相對路徑)
String url = "jdbc:odbc:driver={Microsoft Access Driver (*.mdb)};DBQ=d://stud.mdb";
第二節 建立與資料來源的串連
一、JDBC驅動程式
一般來說,驅動程式是由資料庫廠商提供的,目前JDBC驅動程式共有四種類型:
第一種 JDBC-ODBC橋加ODBC驅動程式
這是Sun公司最早實現的JDBC 驅動程式,當時主要目的在於快速推廣JDBC,以便業界接納這個標準。實際上這種驅動程式就是把JDBC API映射到ODBC API上。JDBC-ODBC 橋接方式利用微軟的開放資料庫互串連口(ODBC API)同資料庫伺服器通訊,用戶端電腦首先應該安裝並配置ODBC driver 和JDBC-ODBC bridge兩種驅動程式。
這種橋接方式最大的問題,是把Java不由自主的和Windows綁定在了一起,失去了Java跨平台的特點,這對於Java應用程式來說是不可接受的。另外Sun所提供的ODBC-JDBC橋不是多線程的,也就是說它不適合在需要並發執行的企業級應用中使用。所以就目前的使用上來看,這種形式的驅動程式已經很少使用了。
第二種 本地API
這種類型的驅動程式把客戶機API上的JDBC調用轉換為Oracle、Sybase、Informix、DB2或其它DBMS的調用。注意,象橋驅動程式一樣,這種類型的驅動程式要求將某些二進位代碼載入到每台客戶機上。
這種驅動方式將資料庫廠商的特殊協議轉換成Java代碼及二進位類碼,使Java 資料庫客戶方與資料庫伺服器方通訊。例如:Oracle用SQLNet協議,DB2用IBM 的資料庫協議。資料庫廠商的特殊協議也應該被安裝在客戶機上。
第三種 JDBC網路純Java驅動程式
在java的早期階段,Applet非常流行的時候,需要用Applet直接存取資料庫,然而Applet安全模式禁止它訪問多個Web伺服器上的資料庫資源,為瞭解決這個問題,這個驅動程式就像Applet訪問資料庫的代理,目前這種形式的驅動程式已經很少用。
這種驅動程式將JDBC轉換為與DBMS無關的網路通訊協定,之後這種協議又被某個伺服器轉換為一種DBMS協議。這種網路伺服器中介軟體能夠將它的純Java客戶機串連到多種
不同的資料庫上。所用的具體協議取決於提供者。通常,這是最為靈活的JDBC驅動程式。有可能所有這種解決方案的提供者都提供適合於Intranet用的產品。為了使這些產品也支援Internet訪問,它們必須處理Web所提出的安全性、通過防火牆的訪問等方面的其他需求。幾家提供者正將JDBC驅動程式加到他們現有的資料庫中介軟體產品中。
這種方式是純Java driver。資料庫客戶以標準網路通訊協定(如HTTP、SHTTP)同資料庫訪問伺服器通訊,資料庫訪問伺服器然後翻譯標準網路通訊協定成為資料庫廠商的專有特殊資料庫訪問協議(也可能用到ODBC driver)與資料庫通訊。對Internet 和Intranet 使用者而言這是一個理想的解決方案。Java driver 被自動的,以透明的方式隨Applets自Web伺服器而下載並安裝在使用者的電腦上。
第四種 本地協議純Java驅動程式
這種類型的驅動程式將JDBC調用直接轉換為DBMS所使用的網路通訊協定。這將允許從客戶機機器上直接調用DBMS伺服器,是Intranet訪問的一個很實用的解決方案。
這種方式也是純Java driver。資料庫廠商提供了特殊的JDBC協議使Java資料庫客戶與資料庫伺服器通訊。然而,將把代理協議同資料庫伺服器通訊改用資料庫廠商的特殊JDBC driver。這對Intranet 應用是高效的,可是資料庫廠商的協議可能不被防火牆支援,缺乏防火牆支援在Internet 應用中會存在潛在的安全隱患。
驅動程式的選擇往往是比較難以定奪的事情,一般來說,第二種驅動程式具有多年使用的優勢,而第四種驅動程式由於避開了本地代碼存在的隱患,相對來說可能比較好,而且比較容易移植。
目前而言,Sybase、Informix、Sql Server都可以使用第四種驅動程式,而Oracle可以使用第二種驅動程式。現在Oracle公司也免費提供第四種類型的驅動程式,可以訪問下面的網址:
http://technet.oracle.com/software/tech/java/sqlj_jdbc/sofrware_index.html
驅動程式的安裝應該仔細閱讀資料庫廠商提供的資料,下面我們以最常用的幾種資料庫為例,討論資料庫驅動程式的配置問題。
二、串連的一般方法
String url="jdbc:odbc:DatabaseDSN";
Connection con=DriverManager.getConnection(url,"Login","Password");
注意:
採用DriverManager類中的getConnection()方法實現與url所指定的資料來源建立串連並返回一個Connection類的對象,以後對這個資料來源的操作都是基於該Connection類對象;但對於Access等小型資料庫,可以不用給出使用者名稱與密碼。
String url="jdbc:odbc:DatabaseDSN";
Connection con=DriverManager.getConnection(url);
System.out.println(con.getCatalog()); //取得資料庫的完整路徑及檔案名稱
JDBC借用了url文法來確定全球的資料庫(資料庫URL類似於通用的URL),對由url所指定的資料來源的表示格式為
jdbc:<subprotocal>:[ database locator]
jdbc---指出要使用JDBC
subprotocal---定義驅動程式類型
database locator---提供網路資料庫的位置和連接埠號碼(包括主機名稱、連接埠和資料庫系統名等)
jdbc:odbc://host.domain.com:port/databasefile
主協議jdbc,驅動程式類型為odbc,它指明JDBC管理器如何訪問資料庫,該例指定為採用JDBC-ODBC橋接方式;其它為資料庫的位置表示。
不同廠商的資料庫系統,主要差別在JDBC的驅動程式及資料庫的url格式。
下面討論一些具體的問題。
三、Access的串連應用
Access資料庫是微軟Office內建的資料庫,在安全性、方便性、使用者介面方面有良好的表現,但它只適合小量使用者使用。
由於它本身就必須在Windows下使用,這裡正好用它說明ODBC-JDBC橋的應用。
資料來源名:FaqAccess
測試代碼:
import java.sql.*;
public class AccessDemo {
public static void main(String[] args) throws Exception {
//FaqAccess指在ODBC上聲明的資料庫名字
String url = "jdbc:odbc:FaqAccess";
String query, subject, answer;
Connection conn; //建立串連類
Statement statement; //建立Sql語句執行類
ResultSet resultSet = null; //建立結果集類
//告訴程式使用jdbc與odbc橋建立資料庫聯結
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
//使用DriverManager類的getConnection()方法建立聯結,第一個字元參數定義使用者名稱,第二個字元參數定義密碼
conn = DriverManager.getConnection(url, "", "");
statement = conn.createStatement(); //建立sql語句執行類
//擷取資料的記錄數
query = "select count(*) as rowCount from faqs";
//使用executeQuery()方法執行sql命令
resultSet = statement.executeQuery(query);
resultSet.next(); //移到資料庫的下一條記錄
//如果記錄為空白,那麼加入十條記錄
if (resultSet.getInt("rowCount")==0){
for(int i = 1; i < 11; ++i){
String sql="insert into faqs values(" + i + ", '問題" + i + "','答案" + i + "')";
//使用executeUpdate()方法執行除查詢之外的sql命令
statement.executeUpdate(sql);
}
}
//獲得資料庫的所有記錄
query = "select * from faqs";
resultSet = statement.executeQuery(query);
//使用next()方法遊歷資料庫的每條記錄
while (resultSet.next()) {
//使用getString()方法取得欄位的內容
subject = resultSet.getString("subject");
answer = resultSet.getString("answer");
System.out.print("問題內容 = " + subject);
System.out.println(", 客案內容 = " + answer);
}
resultSet.close(); //關閉結果集
statement.close(); //關閉sql語句執行類
conn.close(); //關閉資料庫聯結類
}
}
四、SQL Server 2000的串連應用
微軟的SQL Server在中小型資料庫專案上應用非常普遍,它的連線速度快,支援的使用者多,安全性好,而且是可視化介面,所以在國內許多MIS系統上應用非常廣泛。
微軟的驅動程式有三個程式:
msbase.jar
msutil.jar
mssqlserver.jar
我們可以在C盤根目錄下建立一個檔案夾:JDBCSQLSERVER2000。把這三個檔案拷貝過去。
在工作目錄下構造檔案setenv.cmd,
set path=%path%;c:/j2sdk1.4.0/bin;
set CLASSPATH=.;c:/j2sdk1.4.0/lib
set CLASSPATH=%CLASSPATH%.;c:/JDBCSQLSERVER2000/msbase.jar;c:/JDBCSQLSERVER2000/msutil.jar;c:/JDBCSQLSERVER2000/mssqlserver.jar
以設定CLASSPATH路徑。
啟動在運行前需要啟動一下這個檔案,設上路徑。
注意:在UNIX作業系統中,路徑設定為:
CLASSPATH=.;/home/user1/mssqlserver2000jdbc/lib/msbase.jar;/home/user1/mssqlserver2000jdbc/lib/msutil.jar;/home/user1/mssqlserver2000jdbc/lib/mssqlserver.jar
可以做一個小的例子,實驗資料庫調用情況:
檔案名稱:SqlDemo.java
import java.*;
import java.lang.*;
import java.sql.*;
public class SqlDemo {
public static void main(String[] args) throws Exception {
//聲明串連,SQL語句執行對象和結果集變數
java.sql.Connection conn = null;
java.sql.Statement stmt = null;
java.sql.ResultSet rs = null;
//載入資料庫驅動程式
//Driver Classname=com.microsoft.jdbc.sqlserver.SQLServerDriver
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
//建立串連
//url=jdbc:microsoft:sqlserver://COMMONOR-02A84C:1433
//Properties
//Password=
//DatabaseName=pubs
//User=sa
//電腦名稱要根據實際情況更改
conn = DriverManager.getConnection("jdbc:microsoft:sqlserver://COMMONOR-02A84C:1433;DatabaseName=pubs;User=sa;Password=");
//建立SQL語句對象
stmt = conn.createStatement();
//執行SQL語句
stmt.execute("select * from employee");
//取得結果集
rs = stmt.getResultSet();
//列印結果
while (rs.next()) {
System.out.println(rs.getString("fname") + " - " + rs.getString("lname") + " - " + rs.getString("job_id"));
}
rs.close(); //關閉結果集
stmt.close(); //關閉sql語句執行類
conn.close(); //關閉資料庫聯結類
}
}
編譯,運行,應該能夠正常工作。