正如一個Connection對象創建Statement和PreparedStatement對象,它也創造了CallableStatement對像這將被用來執行調用數據庫存儲過程。
創建CallableStatement對象:
假設,需要執行以下Oracle存儲過程:
CREATE OR REPLACE PROCEDURE getEmpName (EMP_ID IN NUMBER, EMP_FIRST OUT VARCHAR) ASBEGIN 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對象可以使用所有的三個。
這裡是每個定義:
下面的代碼片段顯示瞭如何使用該Connection.prepareCall()方法實例化基於上述存儲過程CallableStatement對象:
CallableStatement cstmt = null;try { String SQL = "{call getEmpName (?, ?)}"; cstmt = conn.prepareCall (SQL); . . .}catch (SQLException e) { . . .}finally { . . .}String變量的SQL表示存儲過程,使用參數佔位符。
使用CallableStatement對像是使用PreparedStatement對象。必須將值綁定到所有的參數執行該語句之前,否則將收到一個SQLException。
如果有IN參數,只要按照適用於PreparedStatement對象相同的規則和技巧;使用對應於要綁定Java數據類型的setXXX()方法。
當使用OUT和INOUT參數就必須採用額外CallableStatement方法的registerOutParameter()。 registerOutParameter()方法JDBC數據類型綁定到數據類型的存儲過程返回。
一旦調用存儲過程,用getXXX()方法的輸出參數檢索值。這種方法投射SQL類型的值檢索到Java數據類型。
關閉CallableStatement 對象:
正如關閉其他Statement對象,出於同樣的原因,也應該關閉CallableStatement對象。
close()方法簡單的調用將完成這項工作。如果關閉了Connection對象首先它會關閉CallableStatement對象為好。然而,應該始終明確關閉的CallableStatement對象,以確保正確的清除。
CallableStatement cstmt = null;try { String SQL = "{call getEmpName (?, ?)}"; cstmt = conn.prepareCall (SQL); . . .}catch (SQLException e) { . . .}finally { cstmt.close();} PS:CallableStatement對象實例
下面是利用CallableStatement連同下列getEmpName()的MySQL存儲過程的例子:
請確定已經在EMP數據庫中創建該存儲過程。可以使用MySQL查詢瀏覽器來完成它。
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 ;
基於對環境和數據庫安裝在前面的章節中進行,這個範例程式碼已被寫入。
複製下面的例子中JDBCExample.java,編譯並運行,如下所示:
//STEP 1. Import required packagesimport java.sql.*;public class JDBCExample { // JDBC driver name and database URL static final String JDBC_DRIVER = "com.mysql.jdbc.Driver"; static final String DB_URL = "jdbc:mysql://localhost/EMP"; // Database credentials static final String USER = "username"; static final String PASS = "password"; public static void main(String[] args) { Connection conn = null; CallableStatement stmt = null; try{ //STEP 2: Register JDBC driver Class.forName("com.mysql.jdbc.Driver"); //STEP 3: Open a connection System.out.println("Connecting to database..."); conn = DriverManager.getConnection(DB_URL,USER,PASS); //STEP 4: Execute a query System.out.println("Creating statement..."); String sql = "{call getEmpName (?, ?)}"; stmt = conn.prepareCall(sql); //Bind IN parameter first, then bind OUT parameter int empID = 102; stmt.setInt(1, empID); // This would set ID as 102 // Because second parameter is OUT so register it stmt.registerOutParameter(2, java.sql.Types.VARCHAR); //Use execute method to run stored procedure. System.out.println("Executing stored procedure..." ); stmt.execute(); //Retrieve employee name with getXXX method String empName = stmt.getString(2); System.out.println("Emp Name with ID:" + empID + " is " + empName); stmt.close(); conn.close(); }catch(SQLException se){ //Handle errors for JDBC se.printStackTrace(); }catch(Exception e){ //Handle errors for Class.forName e.printStackTrace(); }finally{ //finally block used to close resources try{ if(stmt!=null) stmt.close(); }catch(SQLException se2){ }// nothing we can do try{ if(conn!=null) conn.close(); }catch(SQLException se){ se.printStackTrace(); }//end finally try }//end try System.out.println("Goodbye!");}//end main}//end JDBCExample現在編譯上面的例子如下:
C:>javac JDBCExample.java
當運行JDBCExample,它會產生以下結果:
C:>java JDBCExample
Connecting to database...Creating statement...Executing stored procedure...Emp Name with ID:102 is ZaidGoodbye!
JDBC的SQL轉義語法:
轉義語法使能夠使用通過使用標準的JDBC方法和屬性,無法使用數據庫的某些特性的靈活性。
一般的SQL轉義語法格式如下:
{keyword 'parameters'}這裡有以下這些,會發現非常有用的,而這樣做的JDBC編程的轉義序列:
d, t, ts 關鍵字:
他們幫助確定日期,時間和時間戳記文字。如所知,沒有兩個數據庫管理系統是基於時間和日期的方式相同。此轉義語法告訴驅動程序呈現在目標數據庫的格式,日期或時間。實現例子:
{d 'yyyy-mm-dd'}其中yyyy=年,mm =月,DD =日。使用這種語法{d '2009-09-03'}是2009年3月9日。
下面是一個簡單的例子說明如何插入日期表:
//Create a Statement objectstmt = conn.createStatement();//Insert data ==> ID, First Name, Last Name, DOBString sql="INSERT INTO STUDENTS VALUES" + "(100,'Zara','Ali', {d '2001-12-16'})";stmt.executeUpdate(sql);同樣,可以使用以下兩種語法之一,無論是t 或ts:
{t 'hh:mm:ss'}其中hh=小時,mm=分,ss=秒。使用此語法{t '13:30:29'}是下午1點三十分29秒.
{ts 'yyyy-mm-dd hh:mm:ss'}這是上述兩種語法'd' 和't' 來表示時間戳結合語法。
escape 關鍵字:
該關鍵字標識LIKE子句中使用的轉義字符。有用使用SQL通配符%,其中匹配零個或多個字符時。例如:
String sql = "SELECT symbol FROM MathSymbols WHERE symbol LIKE '/%' {escape ''}";stmt.execute(sql);如果使用反斜杠字符()作為轉義字符,還必須使用兩個反斜杠字符在Java字符串字面,因為反斜杠也是一個Java轉義字符。
fn 關鍵字:
此關鍵字代表在DBMS中使用標量函數。例如,可以使用SQL length函數計算GE字符串的長度:
{fn length('Hello World')}這將返回11,字符串'Hello World'的長度。 .
call 關鍵字:
此關鍵字是用來調用存儲過程。例如,對於一個存儲過程,需要一個IN參數,請使用以下語法:
{call my_procedure(?)};對於一個存儲過程,需要一個IN參數並返回一個OUT參數,使用下面的語法:
{? = call my_procedure(?)}; oj 關鍵字:
此關鍵字用來表示外部聯接。其語法如下:
{oj outer-join}外連接表={LEFT| RIGHT| FULL}外連接{表|外連接}的搜索條件。例如:
String sql = "SELECT Employees FROM {oj ThisTable RIGHT OUTER JOIN ThatTable on id = '100'}";stmt.execute(sql);