JDBC Statements, PreparedStatement和CallableStatement語句

當獲得了與數據庫的連接後,就可以與數據庫進行交互了。 JDBC StatementCallableStatementPreparedStatement接口定義了可用於發送SQL或PL/SQL命令,並從數據庫接收數據的方法和屬性。

它們還定義了有助於在Java和SQL數據類型的數據類型差異轉換的方法。
下表提供了每個接口定義,以及使用這些接口的目的的總結。

接口

推薦使用

Statement

用於對數據庫進行通用訪問,在運行時使用靜態SQL語句時很有用。 Statement接口不能接受參數。

PreparedStatement

當計劃要多次使用SQL語句時使用。PreparedStatement接口在運行時接受輸入參數。

CallableStatement

當想要訪問數據庫存儲過程時使用。CallableStatement接口也可以接受運行時輸入參數。

1. Statement對象

1.1. 創建Statement對象

在使用Statement對象執行SQL語句之前,需要使用Connection對象的createStatement()方法創建一個Statement對象,如以下示例所示:

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

在創建Statement對象後,可以使用它來執行一個SQL語句,它有三個執行方法可以執行。它們分別是 -

  • boolean execute (String SQL) : 如果可以檢索到ResultSet對象,則返回一個布爾值true; 否則返回false。使用此方法執行SQLDDL語句或需要使用真正的動態SQL,可使用於執行創建數據庫,創建表的SQL語句等等。
  • int executeUpdate (String SQL): 返回受SQL語句執行影響的行數。使用此方法執行預期會影響多行的SQL語句,例如:INSERTUPDATEDELETE語句。
  • ResultSet executeQuery(String SQL):返回一個ResultSet對象。 當您希望獲得結果集時,請使用此方法,就像使用SELECT語句一樣。

1.2. 關閉Statement對象

就像關閉一個Connection對象一樣,以保存數據庫資源一樣,由於同樣的原因,還應該關閉Statement對象。

一個簡單的調用close()方法將執行該作業(工作)。 如果先關閉Connection對象,它也會關閉Statement對象。 但是,應該始終顯式關閉Statement對象,以確保正確的清理順序。

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

爲了更好的理解,建議學習Statment示例教程 。

2. PreparedStatement對象

PreparedStatement接口擴展了Statement接口,它添加了比Statement對象更好一些優點的功能。

此語句可以動態地提供/接受參數。

2.1 創建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數組索引不同(它不從0開始)。

所有Statement對象與數據庫交互的方法(a)execute(),(b)executeQuery()和(c)executeUpdate()也可以用於PreparedStatement對象。 但是,這些方法被修改爲可以使用輸入參數的SQL語句。

2.2. 關閉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();
}

爲了更好的理解,建議學習PreparedStatement示例代碼 。

3. CallableStatement對象

類似Connection對象創建StatementPreparedStatement對象一樣,它還可以使用同樣的方式創建CallableStatement對象,該對象將用於執行對數據庫存儲過程的調用。

3.1. 創建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 ;

存在三種類型的參數:INOUTINOUTPreparedStatement對象只使用IN參數。CallableStatement對象可以使用上面三個參數類型。

以下是上面三種類型參數的定義 -

參數

描述

IN

創建SQL語句時其參數值是未知的。 使用setXXX()方法將值綁定到IN參數。

OUT

由SQL語句返回的參數值。可以使用getXXX()方法從OUT參數中檢索值。

INOUT

提供輸入和輸出值的參數。使用setXXX()方法綁定變量並使用getXXX()方法檢索值。

以下代碼片段顯示瞭如何使用Connection.prepareCall()方法根據上述存儲過程來實例化一個CallableStatement對象 -

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

String變量strSQL表示存儲過程,帶有兩個參數佔位符。

使用CallableStatement對象就像使用PreparedStatement對象一樣。 在執行語句之前,必須將值綁定到所有參數,否則將拋出一個SQLException異常。

如果有IN參數,只需遵循適用於PreparedStatement對象的相同規則和技術; 使用與綁定的Java數據類型相對應的setXXX()方法。

使用OUTINOUT參數時,必須使用一個額外的CallableStatement對象方法registerOutParameter()registerOutParameter()方法將JDBC數據類型綁定到存儲過程並返回預期數據類型。

當調用存儲過程,可以使用適當的getXXX()方法從OUT參數中檢索該值。 此方法將檢索到的SQL類型的值轉換爲對應的Java數據類型。

關閉CallableStatement對象

就像關閉其他Statement對象一樣,由於同樣的原因(節省數據庫系統資源),還應該關閉CallableStatement對象。

簡單的調用close()方法將執行關閉CallableStatement對象。 如果先關閉Connection對象,它也會關閉CallableStatement對象。 但是,應該始終顯式關閉CallableStatement對象,以確保按正確順序的清理資源。

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

爲了更好的理解,建議參考學習Callable示例代碼。