當獲得了與資料庫的連線後,就可以與資料庫進行互動了。 JDBC Statement
,CallableStatement
和PreparedStatement
介面定義了可用於傳送SQL或PL/SQL命令,並從資料庫接收資料的方法和屬性。
它們還定義了有助於在Java和SQL資料型別的資料型別差異轉換的方法。
下表提供了每個介面定義,以及使用這些介面的目的的總結。
介面 | 推薦使用 |
---|---|
Statement |
用於對資料庫進行通用存取,在執行時使用靜態SQL語句時很有用。 Statement 介面不能接受引數。 |
PreparedStatement |
當計劃要多次使用SQL語句時使用。PreparedStatement 介面在執行時接受輸入引數。 |
CallableStatement |
當想要存取資料庫儲存過程時使用。CallableStatement 介面也可以接受執行時輸入引數。 |
在使用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
語句一樣。就像關閉一個Connection
物件一樣,以儲存資料庫資源一樣,由於同樣的原因,還應該關閉Statement
物件。
一個簡單的呼叫close()
方法將執行該作業(工作)。 如果先關閉Connection
物件,它也會關閉Statement
物件。 但是,應該始終顯式關閉Statement
物件,以確保正確的清理順序。
Statement stmt = null;
try {
stmt = conn.createStatement( );
. . .
}
catch (SQLException e) {
. . .
}
finally {
stmt.close();
}
為了更好的理解,建議學習Statment範例教學 。
PreparedStatement
介面擴充套件了Statement
介面,它新增了比Statement
物件更好一些優點的功能。
此語句可以動態地提供/接受引數。
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語句。
就像關閉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範例程式碼 。
類似Connection
物件建立Statement
和PreparedStatement
物件一樣,它還可以使用同樣的方式建立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資料型別。
就像關閉其他Statement
物件一樣,由於同樣的原因(節省資料庫系統資源),還應該關閉CallableStatement
物件。
簡單的呼叫close()
方法將執行關閉CallableStatemen
t物件。 如果先關閉Connection
物件,它也會關閉CallableStatement
物件。 但是,應該始終顯式關閉CallableStatement
物件,以確保按正確順序的清理資源。
CallableStatement cstmt = null;
try {
String SQL = "{call getEmpName (?, ?)}";
cstmt = conn.prepareCall (SQL);
. . .
}
catch (SQLException e) {
. . .
}
finally {
cstmt.close();
}
為了更好的理解,建議參考學習Callable範例程式碼。