热门问题
时间线
聊天
视角

Java資料庫連接

JAVA用于数据库访问的API 来自维基百科,自由的百科全书

Remove ads

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

快速預覽 當前版本, 作業系統 ...
Thumb

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

Remove ads

驅動程式類型

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概述

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

資料類型的對映

更多資訊 SQL類型, Java類型 ...

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

Remove ads

例子

利用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); //关闭自动提交,从而将之后执行的多个SQL语句视为同一个事务(自动提交会使每一个SQL语句执行后提交一次而重新启用新的事务)
 
    /* 在此基于有事務控制的conn執行你的代碼 */
 
    conn.commit(); //最终提交该次事务的修改
} catch (Throwable e) {
    try { 
        conn.rollback(); //回退到上一个事务开始时的状态
    } catch (Throwable ignore) {}
    throw e;
} finally {
    try { conn.setAutoCommit(autoCommitDefault); } catch (Throwable ignore) {}
}
Remove ads

參考文獻

外部連結

Loading content...

參見

Loading content...
Loading related searches...

Wikiwand - on

Seamless Wikipedia browsing. On steroids.

Remove ads