1. 程式人生 > >【JDBC】②JDBC 直接呼叫儲存過程

【JDBC】②JDBC 直接呼叫儲存過程

1. 使用 JDBC API 直接呼叫儲存過程

Java Database Connectivity (JDBC) API 是 J2EE 的一部分,是 Java 語言訪問關係資料庫的基於標準的首要機制,提供了對資料庫訪問和快取管理的直接控制。

JDBC 中的 CallableStatement 物件為所有的關係資料庫管理系統 (RDBMS: Relational Database Management System) 提供了一種標準形式呼叫儲存過程的方法。對儲存過程的呼叫有兩種形式:帶結果引數和不帶結果引數。結果引數是一種輸出引數,是儲存過程的返回值。兩種形式都可帶有數量可變的輸入(IN 引數)、輸出(OUT 引數)或輸入和輸出(INOUT 引數)的引數。

在 JDBC 中呼叫儲存過程的語法 為:{call procedure_name[(?, ?, ...)]};返回結果引數的儲存過程的語法為:{? = call procedure_name[(?, ?, ...)]};不帶引數的儲存過程的語法為:{call procedure_name}。其中,問號代表引數,方括號表示其間的內容是可選項。

使用 CallableStatement 物件呼叫儲存過程的過程如下:

使用 Connection.prepareCall 方法建立一個 CallableStatement 物件。 
使用 CallableStatement.setXXX 方法給輸入引數(IN)賦值。 
使用 CallableStatement.registerOutParameter 方法來指明哪些引數只做輸出引數(OUT),哪些是輸入輸出引數(INOUT)。 
呼叫以下方法之一來呼叫儲存過程:

int CallableStatement.executeUpdate: 儲存過程不返回結果集。 
ResultSet CallableStatement.executeQuery: 儲存過程返回一個結果集。 
Boolean CallableStatement.execute: 儲存過程返回多個結果集。 
int[] CallableStatement.executeBatch: 提交批處理命令到資料庫執行。 

如果儲存過程返回結果集,則得到其結果集。 
呼叫 CallableStatement.getXXX 方法從輸出引數 (OUT) 或者輸入輸出引數 (INOUT) 取值。 
使用完 CallableStatement 物件後,使用 CallableStatement.close 方法關閉 CallableStatement 物件。 
舉例:

清單1是一個使用 executeUpdate 來執行的儲存過程的例子。儲存過程名為 exampleJDBC,含有五個引數,前兩個分別是 String 和 Int 型別的輸入引數,後三個分別是整型,整型和字元型的輸出引數。分別給輸入引數賦值 ”Beijing” 和 2008,執行 executeUpdate 命令後,從後三個輸出引數中可以得到輸出值,沒有結果集返回。需要說明的是,這裡的引數下標是以 1 開始的,與 java 陣列下標以 0 開始不同。


清單 1. 使用 executeUpdate 來執行的儲存過程
Connection con = null;
...
// Create a CallableStatement object
CallableStatement cstmt = con.prepareCall("CALL exampleJDBC (?, ?, ?, ?, ?)");  
cstmt.setString (1, “BeiJing”);  // Set input parametercstmt.setInt (2, 2008);        // Set input parameter
cstmt.registerOutParameter (3, Types.INTEGER);cstmt.registerOutParameter (4, Types.INTEGER);cstmt.registerOutParameter (5, Types.VARCHAR);
cstmt.executeUpdate();  // Call the stored procedure
int goldnumber = cstmt.getInt(3);   // Get the output parameter valuesint silvernumber = cstmt.getInt(4);String errorinfo = cstmt.getString(5);
cstmt.close(); 


當儲存過程返回一個結果集時,只需遍歷該結果集便可以得到儲存過程執行的所有結果。具體例子見清單2。


清單 2. 儲存過程返回一個結果集
CallableStatement cstmt = null;

boolean moreResultSets = cstmt.execute();
ResultSet rs1 = cstmt.getResultSet();
while (rs1.next())
     System.out.println(rs1.getString(1) + " " + rs1.getString(2));
 

當儲存過程返回多個結果集時,遍歷所有結果集才能得到執行的所有結果,使用 getMoreResults() 方法跳轉到下一個結果集。具體例子見清單3。


清單 3. 儲存過程返回多個結果集
CallableStatement cstmt = null;

While (cstmt.getMoreResults()) {
  ResultSet rs2 = cstmt.getResultSet();
  while (rs2.next())
     System.out.println(rs2.getString(1) + " " + rs2.getString(2));
  rs2.close();


如果儲存過程返回多個結果集,每個結果集的資料結構都不一樣,或者某些結果集的資料結構未知,則可以使用 getColumnName() 方法來得到結果集中資料的列名。具體例子見清單 4。


清單 4. 儲存過程返回多個結果集,且每個結果集的資料結構未知或者不一樣
CallableStatement cstmt = null;

boolean moreResultSets = cstmt.execute();
while (moreResultSets) {
    ResultSet rs = cstmt.getResultSet();
    ResultSetMetaData rsmd = rs.getMetaData();
    StringBuffer buffer = new StringBuffer();
    for (int i = 1; i <= rsmd.getColumnCount(); i++){
         buffer.append(rsmd.getColumnName(i)).append("\t");
         System.out.println(buffer.toString());
         while (rs.next()) {
           buffer.setLength(0);
           for (int i = 1; i <= rsmd.getColumnCount(); i++)
                buffer.append(rs.getString(i)).append("\t");
           System.out.println(buffer.toString());
         }
}
rs.close();
    moreResultSets = cstmt.getMoreResults();
}
 


適用場景:

多年來 JDBC 一直是 Java 開發人員進行資料訪問的標準,這是一種穩定且被廣泛證實的技術,目前已經發展成可以提供完全具有快取記憶體和資源池機制的完善的資料庫驅動程式。使用 JDBC 來呼叫儲存過程是最常見的一種方式,由於 JDBC 是最接近於資料庫的 API,因而其效率也是最高的。CallableStatement 物件為所有的 DBMS 提供了標準形式呼叫儲存過程的方法,對於要求實現靈活,執行效率要求比較高應用,直接採用 JDBC API 來實現儲存過程能很好地滿足需要。