鍍金池/ 教程/ Java/ JDBC Statements, PreparedStatement和CallableStatement語句
JDBC Like子句實例
JDBC異常
JDBC排序數(shù)據(jù)實例
JDBC事務保存點(setSavepoint, releaseSavepoint )實例
JDBC結(jié)果集
JDBC Statement對象執(zhí)行批量處理實例
JDBC事務
JDBC SQL語法
JDBC快速入門教程
JDBC創(chuàng)建數(shù)據(jù)庫實例
JDBC流ASCII和二進制數(shù)據(jù)
JDBC刪除表實例
JDBC Statements, PreparedStatement和CallableStatement語句
JDBC WHERE子句條件實例
JDBC插入數(shù)據(jù)實例
JDBC驅(qū)動程序類型
JDBC環(huán)境配置
JDBC數(shù)據(jù)庫連接
JDBC刪除數(shù)據(jù)實例
JDBC PrepareStatement對象執(zhí)行批量處理實例
JDBC刪除數(shù)據(jù)庫實例
JDBC事務提交/回滾實例
JDBC更新數(shù)據(jù)實例
JDBC存儲過程調(diào)用
JDBC教程
JDBC批量處理
JDBC創(chuàng)建表實例
JDBC數(shù)據(jù)類型
JDBC是什么?
JDBC簡單示例代碼
JDBC選擇數(shù)據(jù)庫實例
JDBC查詢數(shù)據(jù)實例

JDBC Statements, PreparedStatement和CallableStatement語句

當獲得了與數(shù)據(jù)庫的連接后,就可以與數(shù)據(jù)庫進行交互了。 JDBC StatementCallableStatementPreparedStatement接口定義了可用于發(fā)送SQL或PL/SQL命令,并從數(shù)據(jù)庫接收數(shù)據(jù)的方法和屬性。

它們還定義了有助于在Java和SQL數(shù)據(jù)類型的數(shù)據(jù)類型差異轉(zhuǎn)換的方法。
下表提供了每個接口定義,以及使用這些接口的目的的總結(jié)。

接口 推薦使用
Statement 用于對數(shù)據(jù)庫進行通用訪問,在運行時使用靜態(tài)SQL語句時很有用。 Statement接口不能接受參數(shù)。
PreparedStatement 當計劃要多次使用SQL語句時使用。PreparedStatement接口在運行時接受輸入?yún)?shù)。
CallableStatement 當想要訪問數(shù)據(jù)庫存儲過程時使用。CallableStatement接口也可以接受運行時輸入?yún)?shù)。

1. Statement對象

1.1. 創(chuàng)建Statement對象

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

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

在創(chuàng)建Statement對象后,可以使用它來執(zhí)行一個SQL語句,它有三個執(zhí)行方法可以執(zhí)行。它們分別是 -

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

1.2. 關(guān)閉Statement對象

就像關(guān)閉一個Connection對象一樣,以保存數(shù)據(jù)庫資源一樣,由于同樣的原因,還應該關(guān)閉Statement對象。

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

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

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

2. PreparedStatement對象

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

此語句可以動態(tài)地提供/接受參數(shù)。

2.1 創(chuàng)建PreparedStatement對象

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

JDBC中的所有參數(shù)都由 ? 符號作為占位符,這被稱為參數(shù)標記。 在執(zhí)行SQL語句之前,必須為每個參數(shù)(占位符)提供值。

setXXX()方法將值綁定到參數(shù),其中XXX表示要綁定到輸入?yún)?shù)的值的Java數(shù)據(jù)類型。 如果忘記提供綁定值,則將會拋出一個SQLException。

每個參數(shù)標記是它其順序位置引用。第一個標記表示位置1,下一個位置2等等。 該方法與Java數(shù)組索引不同(它不從0開始)。

所有Statement對象與數(shù)據(jù)庫交互的方法(a)execute(),(b)executeQuery()和(c)executeUpdate()也可以用于PreparedStatement對象。 但是,這些方法被修改為可以使用輸入?yún)?shù)的SQL語句。

2.2. 關(guān)閉PreparedStatement對象

就像關(guān)閉Statement對象一樣,由于同樣的原因(節(jié)省數(shù)據(jù)庫系統(tǒng)資源),也應該關(guān)閉PreparedStatement對象。

簡單的調(diào)用close()方法將執(zhí)行關(guān)閉。 如果先關(guān)閉Connection對象,它也會關(guān)閉PreparedStatement對象。 但是,應該始終顯式關(guān)閉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對象創(chuàng)建StatementPreparedStatement對象一樣,它還可以使用同樣的方式創(chuàng)建CallableStatement對象,該對象將用于執(zhí)行對數(shù)據(jù)庫存儲過程的調(diào)用。

3.1. 創(chuàng)建CallableStatement對象

假設需要執(zhí)行以下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數(shù)據(jù)庫,可使用以下方式來編寫MySQL相同的存儲過程,如下在EMP數(shù)據(jù)庫中創(chuàng)建它 -

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 ;

存在三種類型的參數(shù):INOUTINOUT。 PreparedStatement對象只使用IN參數(shù)。CallableStatement對象可以使用上面三個參數(shù)類型。

以下是上面三種類型參數(shù)的定義 -

參數(shù) 描述
IN 創(chuàng)建SQL語句時其參數(shù)值是未知的。 使用setXXX()方法將值綁定到IN參數(shù)。
OUT 由SQL語句返回的參數(shù)值??梢允褂?code>getXXX()方法從OUT參數(shù)中檢索值。
INOUT 提供輸入和輸出值的參數(shù)。使用setXXX()方法綁定變量并使用getXXX()方法檢索值。

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

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

String變量strSQL表示存儲過程,帶有兩個參數(shù)占位符。

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

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

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

當調(diào)用存儲過程,可以使用適當?shù)?code>getXXX()方法從OUT參數(shù)中檢索該值。 此方法將檢索到的SQL類型的值轉(zhuǎn)換為對應的Java數(shù)據(jù)類型。

關(guān)閉CallableStatement對象

就像關(guān)閉其他Statement對象一樣,由于同樣的原因(節(jié)省數(shù)據(jù)庫系統(tǒng)資源),還應該關(guān)閉CallableStatement對象。

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

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

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