【转】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 存储过程名}。

 

原文地址:https://www.cnblogs.com/qqzy168/p/3138072.html