@@ -10,9 +10,9 @@ JDBC(Java DataBase Connectivity)是用於執行 SQL 的 Java 解決方案,
1010
1111在正式使用 JDBC 進行資料庫操作之前,先來認識一下 JDBC 的基本架構,了解資料庫驅動程式與資料庫之間的關係,在這個小節也將看到,如何設計一個簡單的工具類別,讓您在進行資料庫連接(Connection)時更為方便。
1212
13- 20.1.1 簡介 JDBC
13+ ### 20.1.1 簡介 JDBC
1414
15- 如果要連接資料庫並進行操作,基本上必須了解所使用的資料庫所提供的 API 操作介面,然而各個廠商所提供的 API 操作介面並不一致,如果今天要使用A廠商的資料庫 ,就必須設計一個專用的程式來操作 A 廠商資料庫所提供的 API,將來如果要使用 B 廠商的資料庫,即使目的相同,也是要撰寫專用於 B 廠商資料庫之程式,十分的不方便。
15+ 如果要連接資料庫並進行操作,基本上必須了解所使用的資料庫所提供的 API 操作介面,然而各個廠商所提供的 API 操作介面並不一致,如果今天要使用 A 廠商的資料庫 ,就必須設計一個專用的程式來操作 A 廠商資料庫所提供的 API,將來如果要使用 B 廠商的資料庫,即使目的相同,也是要撰寫專用於 B 廠商資料庫之程式,十分的不方便。
1616
1717使用 JDBC,可由廠商實作操作資料庫介面的驅動程式,而 Java 程式設計人員呼叫 JDBC 的 API 並操作 SQL,實際對資料庫的操作由 JDBC 驅動程式負責,如果要更換資料庫,基本上只要更換驅動程式,Java 程式中只要載入新的驅動程式來源即可完成資料庫的變更,Java 程式的部份則無需改變。
1818
@@ -62,7 +62,7 @@ JDBC 資料庫驅動程式依實作方式可以分為四個類型:
6262
6363### 20.1.2 連接資料庫
6464
65- 為了要連接資料庫系統,您必須要有JDBC驅動程式,由於接下來將使用 MySQL 資料庫進行操作,所以請將下載回來的tar.gz檔案使用解壓縮軟體解開 ,並將當中的 mysql-connector-java-* .jar 加入至 Classpath 的設定之中,假設是放在 c:\workspace\library\mysql-connector-java-3.1.13-bin.jar,則 Classpath 中必須有 c:\workspace\library\mysql-connector-java-3.1.13-bin.jar 這個路徑設定。
65+ 為了要連接資料庫系統,您必須要有JDBC驅動程式,由於接下來將使用 MySQL 資料庫進行操作,所以請將下載回來的 tar.gz 檔案使用解壓縮軟體解開 ,並將當中的 mysql-connector-java-* .jar 加入至 Classpath 的設定之中,假設是放在 c:\workspace\library\mysql-connector-java-3.1.13-bin.jar,則 Classpath 中必須有 c:\workspace\library\mysql-connector-java-3.1.13-bin.jar 這個路徑設定。
6666
6767在 Java SE 中與資料庫操作相關的 JDBC 類別都位於 java.sql 套件中,要連接資料庫,基本上必須有幾個動作:
6868
@@ -83,7 +83,7 @@ JDBC 資料庫驅動程式依實作方式可以分為四個類型:
8383
8484 協定:子協定:資料來源識別
8585
86- 「協定」在 JDBC 中總是 jdbc 開始;「子協定」是橋接的驅動程式或是資料庫管理系統名稱,使用 MySQL 的話是 " mysql" ;「資料來源識別」標出找出資料庫來源的位址與連接埠。舉個例子來說,MySQL 的 JDBC URL 撰寫方式如下:
86+ 「協定」在 JDBC 中總是 jdbc 開始;「子協定」是橋接的驅動程式或是資料庫管理系統名稱,使用 MySQL 的話是 ` mysql ` ;「資料來源識別」標出找出資料庫來源的位址與連接埠。舉個例子來說,MySQL 的 JDBC URL 撰寫方式如下:
8787
8888 jdbc:mysql://主機名稱:連接埠/資料庫名稱?參數=值&參數=值
8989
@@ -126,7 +126,7 @@ getConnection() 方法可以在參數上指定使用者名稱與密碼,例如
126126
127127您可以將 JDBC URL、使用者名稱與密碼等設定資訊,撰寫在一個屬性檔案當中,由程式讀取這個屬性檔中的資訊,如果需要變更資訊,則只要修改屬性檔即可,無須修改程式、重新編譯,在 Java SE 當中,屬性檔的讀取可以交給 java.util.Properties 類別。
128128
129- 舉個實際的例子,假設您使用了以下的指令在MySQL後建立了demo資料庫 :
129+ 舉個實際的例子,假設您使用了以下的指令在 MySQL 後建立了 demo 資料庫 :
130130
131131 CREATE DATABASE demo;
132132
@@ -192,7 +192,7 @@ public class SimpleDBSource implements DBSource {
192192}
193193```
194194
195- 預設的建構方法設定中,是讀取 jdbc.properties 檔案中的設定,如果打算自行指定屬性檔案名稱,則可以使用另一個有參數的建構方法。Properties 的 getProperty() 方法會讀取屬性檔案中的" 鍵(Key)" 對應的" 值(Value)" ,假設您的屬性檔案設定如下:
195+ 預設的建構方法設定中,是讀取 jdbc.properties 檔案中的設定,如果打算自行指定屬性檔案名稱,則可以使用另一個有參數的建構方法。Properties 的 getProperty() 方法會讀取屬性檔案中的 ** 鍵(Key)** 對應的 ** 值(Value)** ,假設您的屬性檔案設定如下:
196196
197197#### ** 範例 20.3 jdbc.properties**
198198```
@@ -376,7 +376,7 @@ onlyfun.caterpillar.poolmax=10
376376
377377 Statement stmt = conn.createStatement();
378378
379- 取得 Statement 物件之後,可以使用 executeUpdate()、executeQuery() 等方法來執行 SQL,executeUpdate() 主要是用來執行 CREATE TABLE、INSERT、DROP TABLE、ALTER TABLE 等會改變資料庫內容的 SQL,例如可以在 demo 資料庫中建立一個 t_message 表格:
379+ 取得 Statement 物件之後,可以使用 executeUpdate()、executeQuery() 等方法來執行 SQL,executeUpdate() 主要是用來執行 CREATE TABLE、INSERT、DROP TABLE、ALTER TABLE 等會改變資料庫內容的 SQL,例如可以在 demo 資料庫中建立一個 t_message 表格:
380380
381381 Use demo;
382382 CREATE TABLE t_message (
@@ -413,7 +413,7 @@ Statement 的 executeQuery() 方法則是用於 SELECT 等查詢資料庫的 SQL
413413 System.out.print(result.getString(4) + "\t");
414414 }
415415
416- Statement 的 execute() 可以用來執行 SQL,並可以測試所執行的 SQL 是執行查詢或是更新,傳回 true 的話表示 SQL 執行將傳回 ResultSet 表示查詢結果,此時可以使用 getResultSet() 取得 ResultSet 物件,如果 execute() 傳回 false,表示 SQL 執行會傳回更新筆數或沒有結果,此時可以使用 getUpdateCount() 取得更新筆數。如果事先無法得知是進行查詢或是更新,就可以使用 execute()。
416+ Statement 的 execute() 可以用來執行 SQL,並可以測試所執行的 SQL 是執行查詢或是更新,傳回 true 的話表示 SQL 執行將傳回 ResultSet 表示查詢結果,此時可以使用 getResultSet() 取得 ResultSet 物件,如果 execute() 傳回 false,表示 SQL 執行會傳回更新筆數或沒有結果,此時可以使用 getUpdateCount() 取得更新筆數。如果事先無法得知是進行查詢或是更新,就可以使用 execute()。
417417
418418範例 20.8 是個示範新增與查詢資料的範例,當中使用了前一節設計的 SimpleDBSource。注意在查詢結束後,要使用 Statement 的 close() 方法來釋放 Statement 的資源,而最後不使用連接時,也使用了 closeConnection() 來關閉連接。
419419
@@ -580,7 +580,7 @@ public class PreparedStatementDemo {
580580}
581581```
582582
583- setXXX() 方法的第一個參數指定"?"的位置,而第二個參數為要新增至資料表欄位的值,要讓 SQL 執行生效,要執行 executeQuery() 或 executeUpdate() 方法,使用 setXXX() 來設定的參數會一直有效,可以於下一次使用,如果想要清除設定好的參數,可以執行 clearParameters() 方法。以下是這個範例的執行結果參考:
583+ setXXX() 方法的第一個參數指定 "?" 的位置,而第二個參數為要新增至資料表欄位的值,要讓 SQL 執行生效,要執行 executeQuery() 或 executeUpdate() 方法,使用 setXXX() 來設定的參數會一直有效,可以於下一次使用,如果想要清除設定好的參數,可以執行 clearParameters() 方法。以下是這個範例的執行結果參考:
584584
585585 1 justin [email protected] mesage... 586586 2 momor [email protected] message2... @@ -612,7 +612,7 @@ fin.close();
612612如果要從資料庫中取得 BLOB 或 CLOB 資料,您可以如下進行,其中 result 參考一個 ResultSet 的實例:
613613
614614 Blob blob = result.getBlob(2); // 取得BLOB
615- Clob clob = result.getClob(2) // 取得CLOB
615+ Clob clob = result.getClob(2); // 取得CLOB
616616
617617Blob 擁有 getBinaryStream()、getBytes() 等方法,可以取得二進位串流或 byte 等資料,同樣的,Clob 擁有 getCharacterStream()、getSubString() 等方法,可以取得字元串流或子字串等資料,您可以查看 API 文件來獲得更詳細的訊息。
618618
@@ -736,9 +736,9 @@ public class LobDemo {
736736
737737交易是一組原子(Atomic)操作(一組 SQL 執行)的工作單元,這個工作單元中的所有原子操作在進行期間,與其它交易隔離,免於數據來源的交相更新而發生混亂,交易中的所有原子操作,要嘛全部執行成功,要嘛全部失敗(即使只有一個失敗,所有的原子操作也要全部撤消)。
738738
739- 舉個簡單的例子,一個客戶從 A 銀行轉帳至 B 銀行,要做的動作為從A銀行的帳戶扣款 、在 B 銀行的帳戶加上轉帳的金額,兩個動作必須成功,如果有一個動作失敗,則此次轉帳失敗。
739+ 舉個簡單的例子,一個客戶從 A 銀行轉帳至 B 銀行,要做的動作為從 A 銀行的帳戶扣款 、在 B 銀行的帳戶加上轉帳的金額,兩個動作必須成功,如果有一個動作失敗,則此次轉帳失敗。
740740
741- 在 JDB C中 ,可以操作 Connection 的 setAutoCommit() 方法,給它 false 引數,在下達一連串的 SQL 語句後,自行呼叫 Connection 的 commit() 來送出變更,如果中間發生錯誤,則呼叫 rollback() 來撤消所有的執行,一個示範的流程如下所示:
741+ 在 JDBC 中 ,可以操作 Connection 的 setAutoCommit() 方法,給它 false 引數,在下達一連串的 SQL 語句後,自行呼叫 Connection 的 commit() 來送出變更,如果中間發生錯誤,則呼叫 rollback() 來撤消所有的執行,一個示範的流程如下所示:
742742
743743``` java
744744try {
@@ -762,7 +762,7 @@ try {
762762 }
763763```
764764
765- 如果您在交易管理時,僅想要撤回(rollback)某個SQL執行點 ,則您可以設定儲存點(save point),例如:
765+ 如果您在交易管理時,僅想要撤回(rollback)某個 SQL 執行點 ,則您可以設定儲存點(save point),例如:
766766
767767``` java
768768conn. setAutoCommit(false );
@@ -789,7 +789,7 @@ stmt.releaseSavepoint(savepoint);
789789
790790### 20.2.6 批次處理
791791
792- Statement 的 execute 等方法一次只能執行一個 SQL 敘述,如果有多個 SQL 敘述要執行的話,可以使用 executeBatch() 方法,在一次方法呼叫中執行多個 SQL 敘述,以增加執行的效能,您可以使用 addBatch() 方法將要執行的 SQL 敘述加入,然後執行 executeBatch() 即可:
792+ Statement 的 execute 等方法一次只能執行一個 SQL 敘述,如果有多個 SQL 敘述要執行的話,可以使用 executeBatch() 方法,在一次方法呼叫中執行多個 SQL 敘述,以增加執行的效能,您可以使用 addBatch() 方法將要執行的 SQL 敘述加入,然後執行 executeBatch() 即可:
793793
794794``` java
795795conn. setAutoCommit(false );
@@ -802,7 +802,7 @@ stmt.executeBatch();
802802conn. commit();
803803```
804804
805- 在執行 executeBatch() 時而 SQL 有錯誤的情況下,會丟出 BatchUpdateException 例外,您可以由這個例外物件的 getUpdateCounts() 方法取得發生錯誤的SQL句數 ,如果中間有個 SQL 執行錯誤,則應該撤回(rollback)整個批次處理過程的SQL操作 。
805+ 在執行 executeBatch() 時而 SQL 有錯誤的情況下,會丟出 BatchUpdateException 例外,您可以由這個例外物件的 getUpdateCounts() 方法取得發生錯誤的 SQL 句數 ,如果中間有個 SQL 執行錯誤,則應該撤回(rollback)整個批次處理過程的 SQL 操作 。
806806
807807使用 PreparedStatement 也可以進行批次處理,直接來看個例子:
808808
@@ -947,7 +947,7 @@ relative() 方法則從目前游標處指定相對位置,例如若目前在第
947947
948948### 20.2.9 ResultSetMetaData
949949
950- Meta Data 即「資料的資料」(Data about data),ResultSet 用來表示查詢到的資料,而 ResultSe t資料的資料 ,即描述所查詢到的資料背後的資料描述,即用來表示表格名稱、欄位名稱、欄位型態等,這些訊息可以透過 ResultSetMetaData 來取得。
950+ Meta Data 即「資料的資料」(Data about data),ResultSet 用來表示查詢到的資料,而 ResultSet 資料的資料 ,即描述所查詢到的資料背後的資料描述,即用來表示表格名稱、欄位名稱、欄位型態等,這些訊息可以透過 ResultSetMetaData 來取得。
951951
952952範例 20.12 直接示範如何取得查詢到的資料欄位數、表格名稱、欄位名稱與欄位資料型態:
953953
0 commit comments