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：JDBC-ODBC橋**
這種類型的驅動把所有JDBC的調用傳遞給ODBC，再讓後者調用數據庫本地驅動代碼（也就是數據庫廠商提供的數據庫操作二進制代碼庫，例如Oracle中的oci.dll）。
優點：
*只要有對應的ODBC驅動（大部分數據庫廠商都會提供），幾乎可以訪問所有的數據庫。
缺點：
*執行效率比較低，不適合大數據量存取的應用；
*由於需要客戶端預裝對應的ODBC驅動，不適合Internet/Intranet應用。

**類型2：本地API驅動**
這種類型的驅動通過客戶端加載數據庫廠商提供的本地代碼庫（C／C++等）來訪問數據庫，而在驅動程序中則包含了Java代碼。
優點：
*速度快於第一類驅動（但仍比不上第3、第4類驅動）。
缺點
*由於需要客戶端預裝對應的數據庫廠商代碼庫，仍不適合Internet/Intranet應用。

**類型3：網絡協議驅動**
這種類型的驅動給客戶端提供了一個網絡API，客戶端上的JDBC驅動程序使用套接字（Socket）來調用服務器上的中間件程序，後者在將其請求轉化為所需的具體API調用。
優點：
*不需要在客戶端加載數據庫廠商提供的代碼庫，單個驅動程序可以對多個數據庫進行訪問，可擴展性較好。
缺點：
*在中間件層仍需對最終數據進行配置；
*由於多出一箇中間件層，速度不如第四類驅動程序。

**類型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語句的執行過程中發生了例外情況（即錯誤）。

**數據類型的映射**
注：這種類型匹配不是強制性標準，特定的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) {}
}

**參考文獻**

**外部鏈接**
  Sun提供的JDBC驅動程序及其供應商列表-  Sun提供的教程-  Sun Java 2 1.4.2 API date=20100707004111 -  一個訂單系統的原形 date=20120625232718 -  DBAccessor: JDBC數據庫訪問封裝類 date=20120611040336 -  開源的JDBC驅動程序列表 date=20200419161443 - http://blog.csdn.net/cho3en1/article/details/52695808 date=20190610051831 

**參見**
 數據庫- Java- J2SE- J2EE- ODBC- ADO- ADO.NET