JDBC - Statement、PreparedStatement和CallableStatement



獲得連線後,我們可以與資料庫互動。JDBC 的Statement、CallableStatementPreparedStatement介面定義了用於傳送SQL或PL/SQL命令以及從資料庫接收資料的方法和屬性。

它們還定義了有助於彌合Java和資料庫中使用的SQL資料型別之間資料型別差異的方法。

下表總結了每個介面的目的,以幫助您決定使用哪個介面。

介面 推薦用途
Statement 用於對資料庫進行通用訪問。在執行時使用靜態SQL語句時非常有用。Statement介面不能接受引數。
PreparedStatement 當您計劃多次使用SQL語句時使用。PreparedStatement介面在執行時接受輸入引數。
CallableStatement 當您要訪問資料庫儲存過程時使用。CallableStatement介面也可以接受執行時輸入引數。

Statement 物件

建立 Statement 物件

在您可以使用Statement物件執行SQL語句之前,您需要使用Connection物件的createStatement()方法建立一個,如下例所示:

Statement stmt = null;
try {
   stmt = conn.createStatement( );
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   . . .
}

建立Statement物件後,您可以使用其三個execute方法之一來執行SQL語句。

  • boolean execute (String SQL):如果可以檢索ResultSet物件,則返回true布林值;否則,返回false。使用此方法執行SQL DDL語句或當您需要使用真正動態的SQL時。

  • int executeUpdate (String SQL) − 返回受SQL語句執行影響的行數。使用此方法執行您期望獲得受影響行數的SQL語句 - 例如,INSERT、UPDATE或DELETE語句。

  • ResultSet executeQuery (String SQL) − 返回ResultSet物件。當您期望獲得結果集時(如使用SELECT語句時)使用此方法。

關閉 Statement 物件

就像關閉Connection物件以節省資料庫資源一樣,出於同樣的原因,您也應該關閉Statement物件。

簡單地呼叫close()方法即可完成此操作。如果您首先關閉Connection物件,它也會關閉Statement物件。但是,您應該始終顯式關閉Statement物件以確保正確清理。

Statement stmt = null;
try {
   stmt = conn.createStatement( );
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   stmt.close();
}

為了更好地理解,我們建議您學習Statement - 示例教程

PreparedStatement 物件

PreparedStatement介面擴充套件了Statement介面,它為您提供了比通用Statement物件多一些的功能和優勢。

此語句使您可以靈活地動態提供引數。

建立 PreparedStatement 物件

PreparedStatement pstmt = null;
try {
   String SQL = "Update Employees SET age = ? WHERE id = ?";
   pstmt = conn.prepareStatement(SQL);
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   . . .
}

JDBC中的所有引數都由?符號表示,這被稱為引數標記。您必須在執行SQL語句之前為每個引數提供值。

setXXX()方法將值繫結到引數,其中XXX表示您希望繫結到輸入引數的Java資料型別。如果您忘記提供值,將會收到SQLException。

每個引數標記都由其序數位置引用。第一個標記表示位置1,下一個位置2,依此類推。此方法與Java陣列索引不同,Java陣列索引從0開始。

所有與資料庫互動的Statement物件的方法(a)execute()、(b)executeQuery()和(c)executeUpdate()也適用於PreparedStatement物件。但是,這些方法已修改為使用可以輸入引數的SQL語句。

關閉 PreparedStatement 物件

就像關閉Statement物件一樣,出於同樣的原因,您也應該關閉PreparedStatement物件。

簡單地呼叫close()方法即可完成此操作。如果您首先關閉Connection物件,它也會關閉PreparedStatement物件。但是,您應該始終顯式關閉PreparedStatement物件以確保正確清理。

PreparedStatement pstmt = null;
try {
   String SQL = "Update Employees SET age = ? WHERE id = ?";
   pstmt = conn.prepareStatement(SQL);
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   pstmt.close();
}

為了更好地理解,讓我們學習Prepare - 示例程式碼

CallableStatement 物件

就像Connection物件建立Statement和PreparedStatement物件一樣,它也建立CallableStatement物件,該物件將用於執行對資料庫儲存過程的呼叫。

建立 CallableStatement 物件

假設您需要執行以下Oracle儲存過程:

CREATE OR REPLACE PROCEDURE getEmpName 
   (EMP_ID IN NUMBER, EMP_FIRST OUT VARCHAR) AS
BEGIN
   SELECT first INTO EMP_FIRST
   FROM Employees
   WHERE ID = EMP_ID;
END;

注意 - 以上儲存過程是為Oracle編寫的,但我們使用的是MySQL資料庫,因此讓我們編寫以下MySQL儲存過程以在EMP資料庫中建立它:

DELIMITER $$

DROP PROCEDURE IF EXISTS `EMP`.`getEmpName` $$
CREATE PROCEDURE `EMP`.`getEmpName` 
   (IN EMP_ID INT, OUT EMP_FIRST VARCHAR(255))
BEGIN
   SELECT first INTO EMP_FIRST
   FROM Employees
   WHERE ID = EMP_ID;
END $$

DELIMITER ;

存在三種類型的引數:IN、OUT和INOUT。PreparedStatement物件僅使用IN引數。CallableStatement物件可以使用所有三種引數。

以下是每種引數的定義:

引數 描述
IN 在建立SQL語句時值未知的引數。您可以使用setXXX()方法將值繫結到IN引數。
OUT 由SQL語句返回其值的引數。您可以使用getXXX()方法從OUT引數檢索值。
INOUT 提供輸入值和輸出值的引數。您可以使用setXXX()方法繫結變數,並使用getXXX()方法檢索值。

以下程式碼片段顯示瞭如何使用Connection.prepareCall()方法根據前面的儲存過程例項化CallableStatement物件:

CallableStatement cstmt = null;
try {
   String SQL = "{call getEmpName (?, ?)}";
   cstmt = conn.prepareCall (SQL);
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   . . .
}

字串變數SQL表示儲存過程,帶有引數佔位符。

使用CallableStatement物件類似於使用PreparedStatement物件。您必須在執行語句之前將值繫結到所有引數,否則將收到SQLException。

如果您有IN引數,只需遵循適用於PreparedStatement物件的相同規則和技術;使用與您正在繫結的Java資料型別相對應的setXXX()方法。

當您使用OUT和INOUT引數時,必須使用額外的CallableStatement方法registerOutParameter()。registerOutParameter()方法將JDBC資料型別繫結到儲存過程預期返回的資料型別。

呼叫儲存過程後,您可以使用適當的getXXX()方法從OUT引數檢索值。此方法將檢索到的SQL型別的值轉換為Java資料型別。

關閉 CallableStatement 物件

就像關閉其他Statement物件一樣,出於同樣的原因,您也應該關閉CallableStatement物件。

簡單地呼叫close()方法即可完成此操作。如果您首先關閉Connection物件,它也會關閉CallableStatement物件。但是,您應該始終顯式關閉CallableStatement物件以確保正確清理。

CallableStatement cstmt = null;
try {
   String SQL = "{call getEmpName (?, ?)}";
   cstmt = conn.prepareCall (SQL);
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   cstmt.close();
}

為了更好地理解,我建議您學習Callable - 示例程式碼

廣告