【轉】JDBC調用存儲過程之實例講解


JDBC調用存儲過程之實例講解

【說明】:本文主要講解使用JDBC調用存儲過程的各種方案,數據庫使用Oracle(其他數據庫類似)涉及到的數據表均為Oracle自帶的Scott帳號的數據表。

【引言】:存儲過程是數據庫使用的重要技術之一,以其高效率、高安全性見長,而JDBC調用存儲過程也是Java程序員必掌握的技能之一。JDBC調用存儲過程主要使用CallableStatement接口,而對於輸入(in)和輸出(out)參數的處理也比較復雜,本文使用案例並有詳細注解來說明各種情況。

一、調用帶輸入\輸出參數的存儲過程

1. 建立存儲過程

-- 輸入職工號(zgh)、輸出姓名(xm)和工資(gz)

create or replace procedure getNameSalByNo(zgh in emp.empno%type,xm out emp.ename%type,gz out emp.sal%type)

is

begin

select ename,sal into xm,gz from emp where empno=zgh;

end;

 

2. JDBC的調用

package com.tjxz.proc;

import java.sql.CallableStatement;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Types;

public class CallProcedure {

/**

* 調用帶普通參數的存儲過程

* @author icer

* @web http://www.tjxz.com

*/

public static void main(String[] args) {

// 設置JDBC參數信息

String url = "jdbc:oracle:thin:@localhost:1521:orcl";

String uid = "scott";

String pwd = "triger";

try {

// 創建接受返回值的變量(姓名:xm,工資:gz)

String xm="";

float gz=0.0f;

/*

* 准備SQL語句

 

 

* 格式為: {call 存儲過程名{?,?,?}}

* 括號中的問號和存儲過程參數進行匹配

*/

String sql = "{call getNameSalByNo(?,?,?)}";

// 加載驅動程序

Class.forName("oracle.jdbc.driver.OracleDriver");

// 獲取連接對象

Connection con = DriverManager.getConnection(url, uid, pwd);

// 獲取執行對象

CallableStatement cst = con.prepareCall(sql);

// 執行之前要使用setXXX來替換SQL語句中的問號參數

cst.setInt(1, 7788);

// 注冊輸出參數類型(注意索引要和問號的位置對應)

cst.registerOutParameter(2, Types.VARCHAR);

cst.registerOutParameter(3, Types.FLOAT);

// 執行SQL命令

cst.execute();

// 提取輸出參數

xm = cst.getString(2);

gz = cst.getFloat(3);

// 控制台輸出

System.out.println("姓名:" + xm);

System.out.println("工資:" + gz);

// 關閉相關對象

cst.close();

con.close();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

 

3. 輸出結果

姓名:SCOTT

工資:3000.0

 

              二、調用帶參數及返回值的函數

 

1. 建立函數

-- 輸入職工號(zgh),輸出工資(gz)

create or replace function getSalByNo(zgh in emp.empno%type) return emp.sal%type

is

 

 

 

 

 

 

gz emp.sal%type;

begin

select sal into gz from emp where empno=zgh;

return gz;

exception

when others then

return -1;

end;

 

2. JDBC調用

package com.tjxz.proc;

import java.sql.CallableStatement;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.sql.Types;

public class CallFunction {

/**

* 調用帶參數及返回值的函數

* @author icer

* @web http://www.tjxz.com

*/

public static void main(String[] args) {

// 設置JDBC參數信息

String url = "jdbc:oracle:thin:@localhost:1521:orcl";

String uid = "scott";

String pwd = "triger";

try {

// 創建接受返回值的變量(工資:gz)

float gz=0.0f;

/*

* 准備SQL語句

* 格式為: {?=call 函數名{?,?,?}}

* 括號中的問號和函數參數進行匹配,使用?=接受返回值

*/

String sql = "{?=call getSalByNo(?)}";

// 加載驅動程序

Class.forName("oracle.jdbc.driver.OracleDriver");

// 獲取連接對象

Connection con = DriverManager.getConnection(url, uid, pwd);

// 獲取執行對象

CallableStatement cst = con.prepareCall(sql);

 

 

 

 

 

 

// 執行之前要使用setXXX來替換SQL語句中的問號參數

cst.setInt(2, 7788);

// 注冊輸出參數類型(注意索引要和問號的位置對應)

cst.registerOutParameter(1, Types.FLOAT);

// 執行SQL命令

cst.execute();

// 提取輸出參數

gz = cst.getFloat(1);

// 控制台輸出

System.out.println("工資:" + gz);

// 關閉相關對象

cst.close();

con.close();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

 

3. 輸出結果

工資:3000.0

 

              三、調用輸出參數為游標的存儲過程

 

1. 創建存儲過程

-- 輸入部門編號(dno),輸出此部門的所職工信息

/*說明:sys_refcursor為系統已定義的動態游標類型聲明*/

create or replace procedure getEmpByDeptno(dno in emp.deptno%type,emps out sys_refcursor)

is

begin

open emps for select * from emp where deptno=dno;

end;

 

2. JDBC調用

package com.tjxz.proc;

import java.sql.CallableStatement;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import oracle.jdbc.internal.OracleTypes;

 

 

 

 

 

 

public class CallProcedureOfCursor {

/**

* 調用輸出參數為游標的存儲過程

* @author icer

* @web http://www.tjxz.com

*/

public static void main(String[] args) {

// 設置JDBC參數信息

String url = "jdbc:oracle:thin:@localhost:1521:orcl";

String uid = "scott";

String pwd = "triger";

try {

/*

* 准備SQL語句 格式為: {call 存儲過程名{?,?,?}}

* 括號中的問號和存儲過程參數進行匹配

*/

String sql = "{call getEmpByDeptno(?,?)}";

// 加載驅動程序

Class.forName("oracle.jdbc.driver.OracleDriver");

// 獲取連接對象

Connection con = DriverManager.getConnection(url, uid, pwd);

// 獲取執行對象

CallableStatement cst = con.prepareCall(sql);

// 執行之前要使用setXXX來替換SQL語句中的問號參數

cst.setInt(1, 10);

// 注冊輸出參數類型(注意索引要和問號的位置對應)

cst.registerOutParameter(2, OracleTypes.CURSOR);

// 執行SQL命令

cst.execute();

// 提取輸出參數(輸出游標使用ResultSet類型接收)

ResultSet rst = (ResultSet) cst.getObject(2);

// 控制台輸出

System.out.println("EMPNO\tENAME");

System.out.println("----------------------");

while (rst.next()) {

System.out.println(rst.getInt("empno") + "\t"

+ rst.getString("ename"));

}

// 關閉相關對象

rst.close();

cst.close();

con.close();

} catch (ClassNotFoundException e) {

 

 

 

 

 

 

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

 

3. 輸出結果

EMPNO ENAME

----------------------

7782 CLARK

7839 KING

7934 MILLER

 

              四、 調用返回值為游標的函數

 

1. 創建函數

-- 輸入部門編號(dno),返回此部門的所職工信息

/*說明:sys_refcursor為系統已定義的動態游標類型聲明*/

create or replace function getEmpsByDeptno(dno in emp.deptno%type) return sys_refcursor

is

emps sys_refcursor;

begin

open emps for select * from emp where deptno=dno;

return emps;

end;

 

2. JDBC調用

package com.tjxz.proc;

import java.sql.CallableStatement;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import oracle.jdbc.internal.OracleTypes;

public class CallFunctionOfCursor {

/**

* 調用返回值為游標的函數 *

* @author icer

* @web http://www.tjxz.com

*/

 

 

 

 

 

 

public static void main(String[] args) {

// 設置JDBC參數信息

String url = "jdbc:oracle:thin:@localhost:1521:orcl";

String uid = "scott";

String pwd = "triger";

try {

/*

* 准備SQL語句,格式為: {?=call 函數名{?,?,?}}

* 括號中的問號和函數參數進行匹配,使用?=接受返回值

*/

String sql = "{?=call getEmpsByDeptno(?)}";

// 加載驅動程序

Class.forName("oracle.jdbc.driver.OracleDriver");

// 獲取連接對象

Connection con = DriverManager.getConnection(url, uid, pwd);

// 獲取執行對象

CallableStatement cst = con.prepareCall(sql);

// 執行之前要使用setXXX來替換SQL語句中的問號參數

cst.setInt(2, 10);

// 注冊輸出參數類型(注意索引要和問號的位置對應)

cst.registerOutParameter(1, OracleTypes.CURSOR);

// 執行SQL命令

cst.execute();

// 提取輸出參數(輸出游標使用ResultSet類型接收)

ResultSet rst = (ResultSet) cst.getObject(1);

// 控制台輸出

System.out.println("EMPNO\tENAME");

System.out.println("----------------------");

while (rst.next()) {

System.out.println(rst.getInt("empno") + "\t"

+ rst.getString("ename"));

}

// 關閉相關對象

rst.close();

cst.close();

con.close();

} catch (ClassNotFoundException e) {

e.printStackTrace();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

 

 

 

 

 

 

3. 輸出結果同上

              五、 調用自聲明游標類型的存儲過程

 

1. 創建存儲過程

/*不使用系統已聲明的動態游標類型,在程序包中自己聲明動態游標類型*/

-- 創建程序包首部,聲明游標和存儲過程

create or replace package pk_scott

as

-- 聲明動態游標類型

type dcur is ref cursor;

-- 聲明存儲過程

procedure getEmpByDeptno(dno in emp.deptno%type,emps out dcur);

end;

-- 創建程序包體,並實現存儲過程

create or replace package body pk_scott

as

-- 實現存儲過程,輸入部門號返回此部門所有雇員信息

procedure getEmpByDeptno(dno in emp.deptno%type,emps out dcur)

is

begin

open emps for select * from emp where deptno=dno;

end;

end;

 

2. JDBC調用:同上

3. 顯示結果:同上

補充:如果調用不帶任何參數的存儲過程格式為{call 存儲過程名}。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM