[摘]JDBC筆記

linweihan1984發表於2007-10-03
JDBC
  Java Database Connectivity (JDBC)是一個標準的Java API,它由一組類和介面組成,Java應用程式開發人員使用它來訪問資料庫和執行SQL語句。WebLogic JDBC是JDBC規範的企業級實現,它為標準的JDBC API提供了大量的擴充套件

JDBC基礎知識

一、採用JDBC訪問資料庫的基本步驟:
A.載入JDBC驅動程式
B.定義連線URL
C.建立連線
D.建立Statement物件
E.執行查詢或更新
F.結果處理
G.關閉連線

二、載入JDBC驅動程式:
1.為了使程式碼儘可能地靈活,我們要避免對類名的引用進行硬編碼(hard-coding),因此我們可以採用從Properties檔案中載入驅動程式的方法,也可以使用在伺服器中配置資料來源(DataSource)的方法來避免在程式碼中硬編碼

2.在開發過程中要保證CLASSPATH設定中包括驅動程式JAR檔案所在的路徑。在WEB服務
器上部署時要將JAR檔案放在Web應用的WEB-INF/lib目錄下。如果多個Web應用使用相同的資料庫驅動程式可以將JAR檔案放置在伺服器使用的公共目錄<%CATALINA_HOME%>\common\lib中

三、定義連線URL:
載入JDBC驅動程式之後,必須指定資料庫伺服器位置。指向資料庫的URL所使用的協議是:
jdbc:子協議,並且載入伺服器的主機名、埠、資料庫名(或引用)。如:Oracle 的連線URL: 
jdbc:oracle:thin:@192.168.0.71:1521:UMV2
jdbc:oracle:採用Oracle驅動程式
thin:指連線伺服器所採用的模式
@192.168.0.71:伺服器的地址
1521:伺服器的監聽埠
UMV2:資料庫名

四、建立連線:
1.一個資料庫連線(Connection)可以通過其自身的getMetaData()來獲取它的自身資訊
2.預設情況下一個資料庫的連線是自動提交模式的(auto-commit),也就是說每當一個SQL語句
被執行後其改變結果都會被自動提交,如果auto-commit模式被關閉,那麼方法commit()必須被顯式呼叫以提交改變結果,否則的話所有對資料庫操作的結果都不會被儲存

五、建立Statement物件:
在同一時間下,每個Statement物件只能開啟一個ResultSet物件。所以,假如有兩個同樣結果的結果集在交叉訪問,那麼這兩個結果集必定為兩個不同的Statement物件所建立。如果在開啟一個新的結果集的時候存在一個已經開啟的結果集,則這個已經存在的結果集會被隱式的關閉

六、執行查詢或更新:
在Statement物件中可以執行如下的操作:
A.查詢操作:executeQuery(SQL語句) B.維護操作:executeUpdate(SQL語句)
C.批處理操作:executeBath()

七、結果處理:
1.ResultSet中行的第一列索引為1,而非0,訪問ResultSet中的資料時要使用列名,而非索引
 但要注意使用列名作為查詢條件是大小寫敏感的。

2.JDBC1.0中,我們只能在ResultSet中向前移動;在JDBC2.0中,我們可以在ResultSet中向
 下(next)或向上(previous)移動,同樣也可以移到特定的行(relative,absolute)

3.預設情況下ResultSet是不可更新的,且只能向前移動。下面的程式碼顯示瞭如何建立一個可滾動的、對更新敏感的ResultSet

Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
// rs will be scrollable, will not show changes made by others,
// and will be updatable

4.ResultSet和ResultSetMetaData沒有直接提供方法返回查詢所返回的行數。然而,在JDBC
 2.0中,可以通過呼叫last()方法將遊標定位到ResultSet的最後一行,然後呼叫getRow()方
 法獲取當前的行號。在JDBC1.0中,確定行數的惟一方式是重複呼叫ResultSet的next()方法,
 直到它返回false為至

八、關閉連線:
在關閉資料庫連線時應該以ResultSet、Statement、Connection的順序進行

JDBC-PreparedStatement(預備語句)

一、PreparedStatement(預備語句)的建立:
首先按照標準的格式建立引數化語句,在實際使用之前傳送引數到資料庫進行編譯。用問號表示語句中應該為具體的值所替換的位置。每次使用預備語句時,只需要使用相應的setXxx呼叫,替換語句中標記出來的引數。然後就可以和常規的語句一樣,使用executeQuery或execute/executeUpdate修改表中的資料。例如:

Connection connection = DriverManager.getConnection (url,username,password);
// 建立帶問號的引數化語句
String template = " UPDATE music SET price=? WHERE id=? ";
PreparedStatement statement = connection.prepareStatement (template);

float newPrices[] = getNewPrices();
int recordingIDs = getIDs();
for(int i=0; i<recordingIDs.length;i++){
// 用setXxx代替?
statement.setFloat(1,newPrices[i]);
statement.setInt(2,recordingIDs[i]);
// 執行預備語句
statement.execute();}

二、使用PreparedStatement的好處:
1.依賴於伺服器對預編譯查詢的支援,以及驅動程式處理原始查詢的效率,預備語句在效能上的優勢可能有很大的不同。
2.安全是預備語句的另外一個特點,我們推薦在通過HTML表單接受使用者輸入,然後對資料庫進行更新時,一定要使用預備語句或儲存過程。
3.預備語句還能夠正確地處理嵌入在字串中的引號以及處理非字元資料(比如向資料庫傳送序列化後的物件)

JDBC-CallableStatement(可呼叫語句)

一、使用CallableStatement(可呼叫語句)的優缺點:
1.優點:語法錯誤可以在編譯時找出來,而非在執行期間;資料庫儲存過程的執行可能比常規的
SQL查詢快得多;程式設計師只需知道輸入和輸出引數,不需瞭解表的結構。另外,由於資料庫語言能夠訪問資料庫本地的一下兒功能(序列,觸發器,多重遊標),因此用它來編寫儲存過程可能要比使用Java程式語言要簡易一些。
2.缺點:儲存過程的商業邏輯在資料庫伺服器上執行,而非客戶機或Web伺服器。而行業的發展趨勢是儘可能多地將商業邏輯移出資料庫,將它們放在JavaBean元件(或者在大型的系統中,EnterPrise JavaBean元件)中,在Web構架上採用這種方式的主要動機是:資料庫訪問和網路I/O常常是效能的瓶頸。

二、使用CallableStatement在JAVA中呼叫資料庫儲存過程:

1.定義對資料庫過程的呼叫
A.無引數過程:{ call procedure_name}
B. 僅有輸入引數的過程:{call procedure_name(?,?...)}
C.有一個輸出引數的過程:{? Call procedure_name}
D.既有輸入引數又有輸出引數的過程{?=call procedure_name(?,?...)}
在過程的4種形式中要注意過程可能返回多個輸出引數,並且引數的索引值從輸出引數開始。因此前面最後例子中,第一個輸入引數的索引值是2而不是1。
2.為過程準備CallableStatement
String procedure = “{ ? = call procedure_name(?,?) }”;
CallableStatement statement = connection.prepareCall(procedure);
3.提供輸入引數的值
在執行儲存過程之前,我們需要呼叫與所要設定的項以及引數的型別相對應的setXxx,替換標記出來的輸入引數
Statement.setString(2,”name”);
4.註冊輸出引數的型別
我們必須使用registerOutParameter註冊每個輸出引數的JDBC型別
Statement.registerOutParameter(n,type);
5.執行這個儲存過程
Statement.execute();
6.訪問返回的輸出引數
可以通過呼叫getXxx訪問每個對應的輸出引數


例如:
Connection connection = DriverManager.getConnection(url,username,password);
String procedure = “{ ? = call myProc(?,?)}”;
CallableStatement statement = connection.prepareCall(procedure);
statement.setString(2,×××);
statement.setFloat(3,×××);
statement.registerOutParameter(1,Types.INTEGER);
statement.execute();
int row = statement.getInt(1);

JDBC-Transation(事務處理)

一、Transation(事務處理)的概念:
在更新資料庫時,預設情況下,更改是永久性寫入到資料庫。然而這種預設行為可以通過編寫程式來關閉。在自動交付關閉的情況下,如果在更新時發生問題,則對資料庫的每個更改都能夠取消(或者說回退到最初的值)。如果更新成功,那麼之後可以將這些更改永久性提交給資料庫。這種方式也稱為事務管理。
我們需要確保,要麼所有的操作都發生,要麼所有的操作都不發生。這就是事務管理的原則。

二、在JAVA中使用Transation(事務管理)保證資料庫的完整性:
我們使用try-catch-finally塊來正確地應對事務管理,首先,記錄自動提交的當前狀態。然後,在try塊中,呼叫setAutoCommit(false)並執行一系列的查詢或更新。如果發生故障,則在catch塊中呼叫rollback;如果事務成功,則在try塊的結尾呼叫commit。不管哪種方式,都在finally塊中重置自動提交的狀態。例如:

Connection connection = DriverManager.getConnection(url,username,password);
boolean autoCommit = connection.getAutoCommit();
Statement statement;
try{
connection.setAutoCommit(false); // 關閉資料庫的自動提交
statement = connection.createStatement();
statement.execute(…);
statement.execute(..);

connection.commit(); // 如果所有語句執行成功則提交事務
}
catch(SQLException sqle){
connection.rollback(); // 如果有異常發生則回滾所有的事務
}
finally{
if(statement!=null){statement.close();}
connection.setAutoCommit(autoCommit); // 重置自動提交的狀態
}
上面的程式碼中,從DriverManager獲取連線的語句在try/catch塊之外。這樣除非成功獲取連線,否則不會呼叫rollback。如果把獲取連線的語句放在try/catch快之內,一旦在連線成功後發生異常,由於rollback的作用會把已經建立的連線斷開。但是getConnection方法也會丟擲SQLException異常這個異常要麼被外圍的方法重新丟擲,要麼在單獨的try/catch塊內捕獲。
JDBC的常用API

一、Connection介面:
1.createStatement():建立資料庫連線
2.prepareStatement(String sql):建立預處理語句
3.prepareCall(String sql):建立可呼叫語句

4.getAutoCommit():獲取自動提交的模式
5.setAutoCommit():設定自動提交的模式

6.commit():提交所執行的SQL語句
7.rollback():回滾所執行的SQL語句

8.getMetaData():獲取一個DatabaseMetaData物件,該物件包含了有關資料庫的基本資訊

9.close():關閉資料庫連線
10.isClose():判斷資料庫連線是否超時或被顯示關閉

二、Statement介面:
1.execute(String sql):執行SQL語句,如果返回值是結果集則為true,否則為false
2.executeQuery(String sql):執行SQL語句,返回值為ResultSet
3.executeUpdate(String sql):執行SQL語句,返回值為所影響的行數

4.addBatch(String sql):向當前Statement物件的命令列表中新增新的批處理SQL語句
5.clearBatch():清空當前Statement物件的命令列表
6.executeBatch():執行當前Statement物件的批處理語句,返回值為每個語句所影響的函式陣列

7.getConnection():返回建立了該Statement物件的Connection物件

8.getQueryTimeout():獲取等待處理結果的時間
9.setQueryTimeout():設定等待處理結果的時間

三、ResultSet介面:
1.first()/beforeFirst():將遊標移動到ResultSet中第一條記錄(的前面)
2.last()/afterLast():將遊標移動到ResultSet中最後一條記錄(的後面)

3.absolute(int column):將遊標移動到相對於第一行的指定行,負數則為相對於最後一條記錄
4.relative(int rows):將遊標移動到相對於當前行的第幾行,正為向下,負為向上

5.next():將遊標下移一行
6.previous():將遊標上移一行

7.insertRow():向當前ResultSet和資料庫中被插入行處插入一條記錄
8.deleteRow():將當前ResultSet中的當前行和資料庫中對應的記錄刪除
9.updateRow():用當前ResultSet中已更新的記錄更新資料庫中對應的記錄
10.cancelUpdate():取消當前對ResultSet和資料庫中所做的操作

11.findColumn(String columnName):返回當前ResultSet中與指定列名對應的索引

12.getRow():返回ResultSet中的當前行號

13.refreshRow():更新當前ResultSet中的所有記錄

14.getMetaData():返回描述ResultSet的ResultSetMetaData物件

15.isAfterLast(): 是否到了結尾
16.isBeforeFirst(): 是否到了開頭
17.isFirst():是否第一條記錄
18.isLast(): 是否最後一條記錄

19.wasNull():檢查列值是否為NULL值,如果列的型別為基本型別,且資料庫中的值為0,那麼
這項檢查就很重要。由於資料庫NULL也返回0,所以0值和資料庫的NULL不能區分。如果列的型別為物件,可以簡單地將返回值與null比較

20.close():關閉當前ResultSet

四、ResultSetMetaData介面:
1.getColumnCount():返回ResultSet中列的數目
2.getColumnName():返回列在資料庫中的名稱
3.getColumnType():返回列的SQL型別

4.isReadOnly():表示該資料項是否為只讀值
5.isNullable():表示該列是否可以儲存NULL

相關文章