一旦我們獲得了數據庫的連接,我們就可以和數據庫進行交互。JDBC 的 Statement,CallableStatement 和 PreparedStatement 接口定義的方法和屬性,可以讓你發(fā)送 SQL 命令或 PL/SQL 命令到數據庫,并從你的數據庫接收數據。
在數據庫中,它們還定義了幫助 Java 和 SQL 數據類型之間轉換數據差異的方法。
下表提供了每個接口的用途概要,根據實際目的決定使用哪個接口。
接口 | 推薦使用 |
---|---|
Statement | 可以正常訪問數據庫,適用于運行靜態(tài) SQL 語句。 Statement 接口不接受參數。 |
PreparedStatement | 計劃多次使用 SQL 語句, PreparedStatement 接口運行時接受輸入的參數。 |
CallableStatement | 適用于當你要訪問數據庫存儲過程的時候, CallableStatement 接口運行時也接受輸入的參數。 |
在你準備使用 Statement 對象執(zhí)行 SQL 語句之前,你需要使用 Connection 對象的 createStatement() 方法創(chuàng)建一個,如下面的示例所示-
Statement stmt = null;
try {
stmt = conn.createStatement( );
. . .
}
catch (SQLException e) {
. . .
}
finally {
. . .
}
當你創(chuàng)建了一個 Statement 對象之后,你可以用它的三個執(zhí)行方法的任一方法來執(zhí)行 SQL 語句。
boolean execute(String SQL) : 如果 ResultSet 對象可以被檢索,則返回的布爾值為 true ,否則返回 false 。當你需要使用真正的動態(tài) SQL 時,可以使用這個方法來執(zhí)行 SQL DDL 語句。
int executeUpdate(String SQL) : 返回執(zhí)行 SQL 語句影響的行的數目。使用該方法來執(zhí)行 SQL 語句,是希望得到一些受影響的行的數目,例如,INSERT,UPDATE 或 DELETE 語句。
正如你關閉一個 Connection 對象來節(jié)約數據庫資源,出于同樣的原因你也應該關閉 Statement 對象。
簡單的調用 close() 方法就可以完成這項工作。如果你關閉了 Connection 對象,那么它也會關閉 Statement 對象。然而,你應該始終明確關閉 Statement 對象,以確保真正的清除。
Statement stmt = null;
try {
stmt = conn.createStatement( );
. . .
}
catch (SQLException e) {
. . .
}
finally {
stmt.close();
}
為了更好地理解,我們建議你研究學習 Statement 示例教程。
PreparedStatement 接口擴展了 Statement 接口,它讓你用一個常用的 Statement 對象增加幾個高級功能。
這個 statement 對象可以提供靈活多變的動態(tài)參數。
PreparedStatement pstmt = null;
try {
String SQL = "Update Employees SET age = ? WHERE id = ?";
pstmt = conn.prepareStatement(SQL);
. . .
}
catch (SQLException e) {
. . .
}
finally {
. . .
}
JDBC 中所有的參數都被用 ? 符號表示,這是已知的參數標記。在執(zhí)行 SQL 語句之前,你必須賦予每一個參數確切的數值。
setXXX() 方法將值綁定到參數,其中 XXX 表示你希望綁定到輸入參數的 Java 數據類型。如果你忘了賦予值,你將收到一個 SQLException。
每個參數標記映射它的序號位置。第一標記表示位置 1 ,下一個位置為 2 等等。這種方法不同于 Java 數組索引,它是從 0 開始的。
所有的 Statement對象 的方法都與數據庫交互,(a) execute(),(b) executeQuery(),及 (c) executeUpdate() 也能被 PreparedStatement 對象引用。然而,這些方法被 SQL 語句修改后是可以輸入參數的。
正如你關閉一個 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();
}
正如一個 Connection 對象可以創(chuàng)建 Statement 對象和 PreparedStatement 對象,它也可以創(chuàng)建被用來執(zhí)行調用數據庫存儲過程的 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 數據庫,那么我們可以在 MySQL 的 EMP 數據庫中創(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 ;
三種類型的參數有:IN,OUT 和 INOUT。PreparedStatement 對象只使用 IN 參數。CallableStatement 對象可以使用所有的三個參數。
這里是每個參數的定義-
參數 | 描述 |
---|---|
IN | 在 SQL 語句創(chuàng)建的時候該參數是未知的。你可以用 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 的 String 變量使用參數占位符表示存儲過程。
使用 CallableStatement 對象就像使用 PreparedStatement 對象。你必須在執(zhí)行該語句之前將值綁定到所有的參數,否則你將收到一個 SQL 異常。
如果你有 IN 參數,只要使用適用于 PreparedStatement 對象相同的規(guī)則和技巧;使用 setXXX() 方法綁定對應的 Java 數據類型。
當你使用 OUT 和 INOUT 參數時,你就必須使用額外的 CallableStatement 方法 - registerOutParameter()。 registerOutParameter() 方法綁定 JDBC 數據類型,該數據是存儲過程返回的值。
一旦你調用存儲過程,你可以用適當的 getXXX() 方法來獲取 OUT 參數的值。這個方法將檢索到的 SQL 類型映射成 Java 數據類型。
正如你關閉其它的 Statement 對象,出于同樣的原因,你也應該關閉 PreparedStatement 對象。
簡單的調用 close() 方法可以完成這項工作。如果你關閉了 Connection 對象,那么它也會關閉 CallableStatement 對象。然而,你應該始終明確關閉 CallableStatement 對象,以確保真正的清除。
CallableStatement cstmt = null;
try {
String SQL = "{call getEmpName (?, ?)}";
cstmt = conn.prepareCall (SQL);
. . .
}
catch (SQLException e) {
. . .
}
finally {
cstmt.close();
}
更多建議: