Java 資料庫連線

Java 資料庫連線，（Java Database Connectivity，簡稱 JDBC）是 Java 語言中用來規範客戶端程式如何來訪問資料庫的應用程式介面，提供了諸如查詢和更新資料庫中資料的方法。JDBC 也是 Sun Microsystems 的商標。JDBC 是面向關係型資料庫的。

在 J2SE 中，提供了一個稱之為 JDBC-ODBC 橋（JDBC-ODBC Bridge）的 API。透過 ODBC，JDBC-ODBC 橋驅動程式可以訪問所有支援 ODBC 的關係型資料庫。與 JDBC API 不同的是，這個驅動程式並不是由 Java 程式碼而是由機器碼（machine code）編寫，並且不是開放原始碼的。

驅動程式型別

JDBC 驅動程式共分四種類型：

1.1 型別 1：JDBC-ODBC 橋

這種型別的驅動把所有 JDBC 的呼叫傳遞給 ODBC，再讓後者呼叫資料庫本地驅動程式碼（也就是資料庫廠商提供的資料庫操作二進位制程式碼庫，例如 Oracle 中的 oci.dll）。

優點：

只要有對應的 ODBC 驅動（大部分資料庫廠商都會提供），幾乎可以訪問所有的資料庫。

缺點：

執行效率比較低，不適合大資料量存取的應用；
由於需要客戶端預裝對應的 ODBC 驅動，不適合 Internet/Intranet 應用。

1.2 型別 2：本地 API 驅動

這種型別的驅動透過客戶端載入資料庫廠商提供的原生代碼庫（C／C++ 等）來訪問資料庫，而在驅動程式中則包含了 Java 程式碼。

優點：

速度快於第一類驅動（但仍比不上第 3、第 4 類驅動）。

缺點

由於需要客戶端預裝對應的資料庫廠商程式碼庫，仍不適合 Internet/Intranet 應用。

1.3 型別 3：網路協議驅動

這種型別的驅動給客戶端提供了一個網路 API，客戶端上的 JDBC 驅動程式使用套接字（Socket）來呼叫伺服器上的中介軟體程式，後者在將其請求轉化為所需的具體 API 呼叫。

優點：

不需要在客戶端載入資料庫廠商提供的程式碼庫，單個驅動程式可以對多個數據庫進行訪問，可擴充套件性較好。

缺點：

在中介軟體層仍需對最終資料進行配置；
由於多出一箇中間件層，速度不如第四類驅動程式。

1.4 型別 4：本地協議驅動

這種型別的驅動使用 Socket，直接在客戶端和資料庫間通訊。

優點：

訪問速度最快；
這是最直接、最純粹的 Java 實現。

缺點：

幾乎只有資料庫廠商自己才能提供這種型別的 JDBC 驅動。
需要針對不同的資料庫使用不同的驅動程式。

API 概述

參看 Java SE 以及 java.sql API

JDBC API 主要位於 JDK 中的 java.sql 包中（之後擴充套件的內容位於 javax.sql 包中），主要包括（斜體代表介面，需驅動程式提供者來具體實現）：

DriverManager：負責載入各種不同驅動程式（Driver），並根據不同的請求，向呼叫者返回相應的資料庫連線（Connection）。
Driver：驅動程式，會將自身載入到 DriverManager 中去，並處理相應的請求並返回相應的資料庫連線（Connection）。
Connection：資料庫連線，負責進行與資料庫間的通訊，SQL 執行以及事務處理都是在某個特定 Connection 環境中進行的。可以產生用以執行 SQL 的 Statement。
Statement：用以執行 SQL 查詢和更新（針對靜態 SQL 語句和單次執行）。
PreparedStatement：用以執行包含動態引數的 SQL 查詢和更新（在伺服器端編譯，允許重複執行以提高效率）。
CallableStatement：用以呼叫資料庫中的儲存過程。
SQLException：代表在資料庫連線的建立和關閉和 SQL 語句的執行過程中發生了例外情況（即錯誤）。

2.1 資料型別的對映

注：這種型別匹配不是強制性標準，特定的 JDBC 廠商可能會改變這種型別匹配。例如 Oracle 中的 DATE 型別是包含時分秒，而 java.sql.Date 僅僅支援年月日。

例子

利用 Class.forName 方法來載入 JDBC 驅動程式（Driver）至 DriverManager：

Class.forName ("com.somejdbcvendor.TheirJdbcDriver");

然後，從 DriverManager 中，透過 JDBC URL，使用者名稱，密碼來獲取相應的資料庫連線（Connection）：

Connection conn = DriverManager.getConnection (

"jdbc:somejdbcvendor:other data needed by some jdbc vendor", // URL

"myLogin", // 使用者名稱

"myPassword" ); // 密碼

不同的 JDBC 驅動程式的 URL 是不同的，它永遠以 “jdbc：” 開始，但後面的內容依照驅動程式型別不同而各異。在獲取 Connection 之後，便可以建立 Statement 用以執行 SQL 語句。下面是一個插入（INSERT）的例子：

Statement stmt = conn.createStatement ;

stmt.executeUpdate ("INSERT INTO MyTable ( name) VALUES ('my name')" );

查詢（SELECT）的結果存放於結果集（ResultSet）中，可以按照順序依次訪問：

Statement stmt = conn.createStatement ;

ResultSet rs = stmt.executeQuery ("SELECT * FROM MyTable");

while (rs.next ) {int numColumns = rs.getMetaData .getColumnCount ;

for ( int i = 1 ; i

但是，通常，Java 程式設計師們更傾向於使用 PreparedStatement。下面的例子使用上例中的 conn 物件：

PreparedStatement ps = null;

ResultSet rs = null;

try {

ps = conn.prepareStatement ( "SELECT i., j. FROM Omega i, Zappa j

WHERE i = ? AND j = ?" );

// 使用問號作為引數的標示

// 進行引數設定

// 與大部分 Java API 中下標的使用方法不同，欄位的下標從 1 開始，1 代表第一個問號

// 當然，還有其他很多針對不同型別的類似的 PreparedStatement.setXXX 方法

ps.setString (1, "Poor Yorick");

ps.setInt (2, 8008);

// 結果集

rs = ps.executeQuery ;

while (rs.next ) {int numColumns = rs.getMetaData .getColumnCount ;

for ( int i = 1 ; i

如果資料庫操作失敗，JDBC 將丟擲一個 SQLException。一般來說，此類異常很少能夠恢復，唯一能做的就是盡可能詳細的列印異常日記。推薦的做法是將 SQLException 翻譯成應用程式領域相關的異常（非強制處理異常）並最終回滾資料庫和通知使用者。

一個資料庫事務程式碼如下：

boolean autoCommitDefault = conn.getAutoCommit ;

try {conn.setAutoCommit (false); // 關閉自動提交，從而將之後執行的多個 SQL 語句視為同一個事務（自動提交會使每一個 SQL 語句執行後提交一次而重新啟用新的事務）

/ 在此基於有事務控制的 conn 執行你的程式碼 /

conn.commit ; // 最終提交該次事務的修改} catch (Throwable e) {

try {conn.rollback ; // 回退到上一個事務開始時的狀態

} catch (Throwable ignore)

throw e;

} finally {try { conn.setAutoCommit (autoCommitDefault); } catch (Throwable ignore) }