JDBC Statements, PreparedStatement和CallableStatement語句
當獲得了與數據庫的連接後,就可以與數據庫進行交互了。 JDBC Statement,CallableStatement和PreparedStatement接口定義了可用於發送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語句,例如:INSERT,UPDATE或DELETE語句。 -
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對象創建Statement和PreparedStatement對象一樣,它還可以使用同樣的方式創建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 ;
存在三種類型的參數: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 strSQL = "{call getEmpName (?, ?)}";
cstmt = conn.prepareCall (SQL);
. . .
}
catch (SQLException e) {
. . .
}
finally {
. . .
}
String變量strSQL表示存儲過程,帶有兩個參數佔位符。
使用CallableStatement對象就像使用PreparedStatement對象一樣。 在執行語句之前,必須將值綁定到所有參數,否則將拋出一個SQLException異常。
如果有IN參數,只需遵循適用於PreparedStatement對象的相同規則和技術; 使用與綁定的Java數據類型相對應的setXXX()方法。
使用OUT和INOUT參數時,必須使用一個額外的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示例代碼。