Java資料庫連線

維基百科,自由的百科全書
前往: 導覽搜尋
Crystal source java.png

Java 資料庫連線,(Java Database Connectivity,簡稱JDBC)是Java語言中用來規範客戶端程式如何來存取資料庫應用程式介面,提供了諸如查詢和更新資料庫中資料的方法。JDBC也是Sun Microsystems商標[1]。JDBC是面向關聯型資料庫的。

J2SE中,提供了一個稱之為JDBC-ODBC橋(JDBC-ODBC Bridge[2])的API。透過ODBC,JDBC-ODBC橋驅動程式可以存取所有支援ODBC的關聯型資料庫。與JDBC API不同的是,這個驅動程式並不是由Java代碼而是由機器碼(native code)編寫,並且不是開放原始碼[3]

驅動程式類型[編輯]

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

類型1:JDBC-ODBC橋[編輯]

這種類型的驅動把所有JDBC的呼叫傳遞給ODBC,再讓後者呼叫資料庫本地驅動代碼(也就是資料庫廠商提供的資料庫操作二進制代碼庫,例如Oracle中的oci.dll)。

優點:

  • 只要有對應的ODBC驅動(大部分資料庫廠商都會提供),幾乎可以存取所有的資料庫。

缺點:

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

類型2:本地API驅動[編輯]

這種類型的驅動透過客戶端載入資料庫廠商提供的本地代碼庫(CC++等)來存取資料庫,而在驅動程式中則包含了Java代碼。

優點:

  • 速度快於第一類驅動(但仍比不上第3、第4類驅動)。

缺點

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

類型3:網路協定驅動[編輯]

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

優點:

  • 不需要在客戶端載入資料庫廠商提供的代碼庫,單個驅動程式可以對多個資料庫進行存取,可延伸性較好。

缺點:

  • 在中介軟體層仍需對最終資料進行配置;
  • 由於多出一個中介軟體層,速度不如第四類驅動程式。

類型4:本地協定驅動[編輯]

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

優點:

  • 存取速度最快;
  • 這是最直接、最純粹的Java實現。

缺點:

  • 因為缺乏足夠的文件和技術支援,幾乎只有資料庫廠商自己才能提供這種類型的JDBC驅動;
  • 需要針對不同的資料庫使用不同的驅動程式。

API概述[編輯]

參看JavaSE以及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語句的執行過程中發生了例外情況(即錯誤)。

資料類型的對映[編輯]

從SQL到Java資料類型對映的JDBC規範
SQL類型 Java類型
CHAR java.lang.String
VARCHAR java.lang.String
LONGVARCHAR java.lang.String
NUMERIC java.math.BigDecimal
DECIMAL java.math.BigDecimal
BIT boolean
TINYINT byte
SMALLINT short
INTEGER int
BIGINT long
REAL float
FLOAT double
DOUBLE double
BINARY byte[]
VARBINARY byte[]
LONGVARBINARY byte[]
DATE java.sql.Date
TIME java.sql.Time
TIMESTAMP java.sql.Timestamp
BLOB java.sql.Blob
CLOB java.sql.Clob
Array java.sql.Array
REF java.sql.Ref
Struct java.sql.Struct

註:這種類型匹配不是強制性標準,特定的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 <= numColumns ; i++ ) {
        // 与大部分Java API中下标的使用方法不同,字段的下标从1开始
        // 当然,还有其他很多的方式(ResultSet.getXXX())获取数据
        System.out.println( "COLUMN " + i + " = " + rs.getObject(i) );
     }
 }
 rs.close();
 stmt.close();

但是,通常,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 <= numColumns ; i++ ) {
        // 与大部分Java API中下标的使用方法不同,字段的下标从1开始
        // 当然,还有其他很多的方式(ResultSet.getXXX())获取数据
        System.out.println( "COLUMN " + i + " = " + rs.getObject(i) );
     }
 
 }
 catch (SQLException e) {
  // 异常处理
 }
 finally { // 使用finally进行资源释放
  try {
   rs.close();
   ps.close();
  } catch( SQLException e){} // 异常处理:忽略close()时的错误
 }

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

一個資料庫事務代碼如下:

boolean autoCommitDefault = conn.getAutoCommit();
try {
    conn.setAutoCommit(false);
 
    /* 在此基于有事务控制的conn执行你的代码 */
 
    conn.commit();
} catch (Throwable e) {
    try { conn.rollback(); } catch (Throwable ignore) {}
    throw e;
} finally {
    try { conn.setAutoCommit(autoCommitDefault); } catch (Throwable ignore) {}
}

參看[編輯]

外部連結[編輯]

  1. ^ [1]
  2. ^ [2]
  3. ^ [3]
資料庫管理系統(DBMS) (檢視 · 討論 · 編輯)

概念
資料庫 · 資料模型 · 資料庫儲存結構英語Database storage structures · 關聯 (資料庫) · 關聯模型 · 分布式資料庫 · ACID ( 原子性英語Atomicity (database systems) · 一致性 · 隔離性 · 永續性英語Durability (database systems) ) · Null值
關聯式資料庫 · 關聯模型 · 資料庫正規化 · 資料庫完整性 · 實體完整性 · 參照完整性英語Referential integrity · 關聯式資料庫管理系統 
主鍵 · 外來鍵 · 代理鍵 · 超鍵 · 候選鍵 

資料庫元件
觸發器 · 檢視 · 資料庫表 · 指標 (資料庫) · 事務日誌英語Transaction log · 資料庫事務 · 並行控制 · 樂觀鎖 · 悲觀鎖 · 資料庫索引 
儲存程式 · 資料庫分割

SQL
分類: 資料查詢語言 (DQL) - 資料定義語言 (DDL) - 資料操縱語言 (DML) - 資料控制語言 (DCL)
指令:SELECT · INSERT · UPDATE · MERGE · DELETE · JOIN · UNION · CREATE · DROP · Begin work · COMMIT · ROLLBACK · TRUNCATE · ALTER
安全: SQL資料隱碼攻擊 · 參數化查詢

資料庫管理系統的實現

實現類型
關聯式資料庫 · 檔案型資料庫 · Deductive · 維度化資料庫 · 階層式 · 圖形資料庫 · 物件資料庫 · 物件關聯式資料庫 · Temporal · XML資料庫

資料庫產品
物件型 (對比) · 關聯型 (對比)

資料庫元件
資料查詢語言 · 查詢最佳化器 · 查詢計畫 · 嵌入式SQL · ODBC · JDBC · OLE DB