一旦獲得連接,我們就可以與數(shù)據(jù)庫(kù)進(jìn)行交互。JDBC Statement、 CallableStatement 和 PreparedStatement 接口定義了方法和屬性,這些方法和屬性使您能夠發(fā)送 SQL 或 PL/SQL 命令并從數(shù)據(jù)庫(kù)接收數(shù)據(jù)。
它們還定義了有助于彌合數(shù)據(jù)庫(kù)中使用的 Java 和 SQL 數(shù)據(jù)類型之間的數(shù)據(jù)類型差異的方法。
下表總結(jié)了每個(gè)接口的用途,以決定要使用的接口。
接口 | 推薦使用 |
---|---|
Statement | 將其用于對(duì)數(shù)據(jù)庫(kù)的通用訪問。在運(yùn)行時(shí)使用靜態(tài)SQL語(yǔ)句時(shí)非常有用。Statement接口不能接受參數(shù)。 |
PreparedStatement | 當(dāng)您計(jì)劃多次使用SQL語(yǔ)句時(shí),請(qǐng)使用此選項(xiàng)。PreparedStatement接口在運(yùn)行時(shí)接受輸入?yún)?shù)。 |
CallableStatement | 當(dāng)您要訪問數(shù)據(jù)庫(kù)存儲(chǔ)過程時(shí),請(qǐng)使用此選項(xiàng)。CallableStatement接口還可以接受運(yùn)行時(shí)輸入?yún)?shù)。 |
在可以使用Statement對(duì)象執(zhí)行SQL語(yǔ)句之前,需要使用Connection對(duì)象的createStatement( )方法創(chuàng)建一個(gè)SQL語(yǔ)句,如以下示例所示-
Statement stmt = null; try { stmt = conn.createStatement( ); . . . } catch (SQLException e) { . . . } finally { . . . }
一旦創(chuàng)建了Statement對(duì)象,就可以使用其三個(gè)執(zhí)行方法之一來執(zhí)行SQL語(yǔ)句。
boolean execute (String SQL):如果可以檢索到ResultSet對(duì)象,則返回布爾值true;否則返回false。當(dāng)需要使用真正的動(dòng)態(tài)SQL時(shí),請(qǐng)使用此方法執(zhí)行SQL DDL語(yǔ)句。
int executeUpdate (String SQL):返回受SQL語(yǔ)句執(zhí)行影響的行數(shù)。使用此方法可以執(zhí)行您希望影響其行數(shù)的SQL語(yǔ)句,例如INSERT,UPDATE或DELETE語(yǔ)句。
ResultSet executeQuery (String SQL):返回一個(gè)ResultSet對(duì)象。當(dāng)您希望獲得結(jié)果集時(shí),請(qǐng)使用此方法,就像使用SELECT語(yǔ)句一樣。
就像關(guān)閉Connection對(duì)象以節(jié)省數(shù)據(jù)庫(kù)資源一樣,出于同樣的原因,您也應(yīng)該關(guān)閉Statement對(duì)象。
一個(gè)簡(jiǎn)單的調(diào)用 close()方法就可以了。如果先關(guān)閉Connection對(duì)象,它也會(huì)關(guān)閉Statement對(duì)象。但是,您應(yīng)該始終顯式關(guān)閉Statement對(duì)象,以確保正確清理。
Statement stmt = null; try { stmt = conn.createStatement( ); . . . } catch (SQLException e) { . . . } finally { stmt.close(); }
為了更好地理解,我們建議您學(xué)習(xí)Statement 示例教程。
PreparedStatement接口擴(kuò)展了Statement接口,它為您提供了附加的功能,與泛型Statement對(duì)象相比具有一些優(yōu)勢(shì)。
該語(yǔ)句使您可以靈活地動(dòng)態(tài)提供參數(shù)。
PreparedStatement pstmt = null; try { String SQL = "Update Employees SET age = ? WHERE id = ?"; pstmt = conn.prepareStatement(SQL); . . . } catch (SQLException e) { . . . } finally { . . . }
JDBC中的所有參數(shù)均由?符號(hào)表示,該符號(hào)稱為參數(shù)標(biāo)記。您必須在執(zhí)行SQL語(yǔ)句之前為每個(gè)參數(shù)提供值。
這些setXXX()方法將值綁定到參數(shù),其中XXX表示您希望綁定到輸入?yún)?shù)的值的Java數(shù)據(jù)類型。如果忘記提供值,則將拋出一個(gè)SQLException。
每個(gè)參數(shù)標(biāo)記都由其順序位置引用。第一個(gè)標(biāo)記代表位置1,第二個(gè)代表位置2,依此類推。此方法與Java數(shù)組索引的方法不同,后者從0開始。
用于與數(shù)據(jù)庫(kù)交互的所有 Statement 對(duì)象的方法(a) execute ()、(b) executeQuery ()和(c) executeUpdate ()也可以與 PreparedStatement 對(duì)象一起使用。但是,這些方法被修改為使用可以輸入?yún)?shù)的 SQL 語(yǔ)句。
與關(guān)閉Statement對(duì)象一樣,出于相同的原因,也應(yīng)該關(guān)閉PreparedStatement對(duì)象。
一個(gè)簡(jiǎn)單的close()方法調(diào)用就可以了。如果先關(guān)閉Connection對(duì)象,它也會(huì)關(guān)閉PreparedStatement對(duì)象。但是,您應(yīng)該始終明確關(guān)閉PreparedStatement對(duì)象,以確保正確清理。
PreparedStatement pstmt = null; try { String SQL = "Update Employees SET age = ? WHERE id = ?"; pstmt = conn.prepareStatement(SQL); . . . } catch (SQLException e) { . . . } finally { pstmt.close(); }
為了更好地理解,讓我們學(xué)習(xí)“PreparedStatement 示例代碼”。
就像 Connection 對(duì)象創(chuàng)建 Statement 和 PreparedStatement 對(duì)象一樣,它也創(chuàng)建 CallableStatement 對(duì)象,該對(duì)象將用于執(zhí)行對(duì)數(shù)據(jù)庫(kù)存儲(chǔ)過程的調(diào)用。
假設(shè)您需要執(zhí)行以下Oracle存儲(chǔ)過程-
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;
NOTE: 上面的存儲(chǔ)過程已經(jīng)為Oracle編寫,但是我們正在使用MySQL數(shù)據(jù)庫(kù),因此,讓我們?yōu)镸ySQL編寫相同的存儲(chǔ)過程,如下所示,以便在EMP數(shù)據(jù)庫(kù)中創(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ù): IN、 OUT 和 INOUT。PreparedStatement 對(duì)象只使用 IN 參數(shù)。CallableStatement 對(duì)象可以使用所有這三個(gè)。
這是每個(gè)的定義-
范圍 | 描述 |
---|---|
IN | 創(chuàng)建 SQL 語(yǔ)句時(shí)值未知的參數(shù)。用 setXXX ()方法將值綁定到 IN something。 |
OUT | 其值由返回的SQL語(yǔ)句提供的參數(shù)。使用getXXX()方法從參數(shù)中檢索值。 |
INOUT | 同時(shí)提供輸入和輸出值的參數(shù)??梢允褂?setXXX ()方法綁定變量,并使用 getXXX ()方法檢索值。 |
下面的代碼片段展示了如何使用 Connection.prepareCall() 方法根據(jù)前面的存儲(chǔ)過程-實(shí)例化 CallableStatement 對(duì)象
CallableStatement cstmt = null; try { String SQL = "{call getEmpName (?, ?)}"; cstmt =conn.prepareCall(SQL); . . . } catch (SQLException e) { . . . } finally { . . . }
字符串變量SQL,表示帶有參數(shù)占位符的存儲(chǔ)過程。
使用CallableStatement對(duì)象與使用PreparedStatement對(duì)象非常相似。您必須在執(zhí)行該語(yǔ)句之前將值綁定到所有參數(shù),否則您將收到一個(gè)SQLException。
如果有 IN 參數(shù),只需遵循應(yīng)用于 PreparedStatement 對(duì)象的相同規(guī)則和技術(shù); 使用與綁定的 Java 數(shù)據(jù)類型對(duì)應(yīng)的 setXXX ()方法。
使用 OUT 和 INOUT 參數(shù)時(shí),必須使用附加的 CallableStatement 方法 registerOutParameter ()。registerOutParameter ()方法將 JDBC 數(shù)據(jù)類型綁定到預(yù)期存儲(chǔ)過程返回的數(shù)據(jù)類型。
調(diào)用存儲(chǔ)過程后,可以使用適當(dāng)?shù)?getXXX() 方法從OUT參數(shù)中檢索值。此方法將檢索到的SQL類型的值轉(zhuǎn)換為Java數(shù)據(jù)類型。
就像關(guān)閉其他Statement對(duì)象一樣,出于同樣的原因,您也應(yīng)該關(guān)閉CallableStatement對(duì)象。
簡(jiǎn)單的調(diào)用close()方法就可以了。如果先關(guān)閉Connection對(duì)象,它也會(huì)關(guān)閉CallableStatement對(duì)象。但是,您應(yīng)該始終顯式關(guān)閉CallableStatement對(duì)象,以確保正確清理。
CallableStatement cstmt = null; try { String SQL = "{call getEmpName (?, ?)}"; cstmt =conn.prepareCall(SQL); . . . } catch (SQLException e) { . . . } finally { cstmt.close(); }
為了更好地理解,我建議學(xué)習(xí)CallableStatement 示例代碼。