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範例程式碼