需要用到的接口

接口 CallableStatement

JDK文档对改接口的说明:

public interface CallableStatement
extends
PreparedStatement

用于执行 SQL 存储过程的接口。JDBC API 提供了一个存储过程 SQL 转义语法,该语法允许对所有 RDBMS 使用标准方式调用存储过程。此转义语法有一个包含结果参数的形式和一个不包含结果参数的形式。如果使用结果参数,则必须将其注册为 OUT 参数。其他参数可用于输入、输出或同时用于二者。参数是根据编号按顺序引用的,第一个参数的编号是 1。

   {?= call <procedure-name>[(<arg1>,<arg2>, ...)]}  -------存储函数的sql,第一个?代表返回类型
{call <procedure-name>[(<arg1>,<arg2>, ...)]} -------存储过程的sql

IN 参数值是使用继承自 PreparedStatement 的 set 方法设置的。在执行存储过程之前,必须注册所有 OUT 参数的类型;它们的值是在执行后通过此类提供的 get 方法获取的。

CallableStatement 可以返回一个 ResultSet 对象或多个 ResultSet 对象。多个 ResultSet 对象是使用继承自 Statement 的操作处理的。

为了获得最大的可移植性,某一调用的 ResultSet 对象和更新计数应该在获得输出参数的值之前处理。

例子程序

对oracle的scott/tiger用户的emp表操作

存储过程,查询员工信息

create or replace procedure queryEmpInfo(eno in number,
pename out varchar2,
psal out number,
pjob out varchar2)
as
begin
select ename,sal,job into pename,psal,pjob from emp where empno=eno;
end;

存储函数:

create or replace function queryEmpImcome(eno in number)
return number
as --变量
psal emp.sal%type;
pcomm emp.comm%type;
begin
select sal,comm into psal,pcomm from emp where empno=eno;
return (psal+nvl(pcomm,0))*12; end;

jdbc工具类

package com.lhy.util;
import java.sql.*; /**
* JDBC工具类 ,一般工具类final。
* 工具类一般不需要new,不需要构造实例。(把构造方法私有)别人就new不了了。
* 此时使用类的方法:
* 1是单例模式(复杂点)
* 2是提供静态的public方法。(简单)
* 本例子是简单的提供public方法实现的。需要静态方法
*
* @author hy
*
*/
public final class JdbcUtils {
private static String url ="jdbc:oracle:thin:@127.0.0.1:1521:ORCL";
private static String user ="scott";
private static String passWord = "tiger"; //构造方法私有,别人不能构造,不会有实例出来.
private JdbcUtils(){ } /**
* 静态代码块,类加载到虚拟机是只执行一次。
*/
static {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) { e.printStackTrace();
} } public static Connection getConnection() {
Connection conn = null;
try {
conn = DriverManager.getConnection(url,user,passWord);
} catch (SQLException e) { e.printStackTrace();
}
return conn; } //释放资源,重载方法。
public static void close(Connection conn) {
try {
if(conn != null){
conn.close();
conn = null;
}
}catch(SQLException e){
e.printStackTrace();
}
}
public static void close(Statement stmt){
try{
if(stmt != null){
stmt.close();
stmt = null;
}
}catch(SQLException e){
e.printStackTrace();
}
}
public static void close(ResultSet rs){
try{
if(rs != null){
rs.close();
rs = null;
}
}catch (SQLException e) {
e.printStackTrace();
}
}
}

测试程序:

public class OracleTest {

    /**
* 测试存储过程
* create or replace procedure queryEmpInfo(eno in number,
pename out varchar2,
psal out number,
pjob out varchar2)
as begin
select ename,sal,job into pename,psal,pjob from emp where empno=eno;
end;
*/
@Test
public void testProcedure(){
//格式 {call <procedure-name>[(<arg1>,<arg2>, ...)]}
String sql = "{call queryEmpInfo(?,?,?,?)}";
Connection conn = null;
CallableStatement call = null; try {
conn = JdbcUtils.getConnection();
call = conn.prepareCall(sql);
//赋值
call.setInt(1, 7839);
//对于out参数,声明
call.registerOutParameter(2, OracleTypes.VARCHAR);
call.registerOutParameter(3, OracleTypes.NUMBER);
call.registerOutParameter(4, OracleTypes.VARCHAR); //调用
call.execute(); //取值
String name = call.getString(2);
double sal = call.getDouble(3);
String job = call.getString(4);
System.err.println(name);
System.err.println(sal);
System.err.println(job);
}catch(Exception e){
e.printStackTrace();
}finally{
JdbcUtils.close(call);
JdbcUtils.close(conn);
}
} /**
* 测试 存储函数
* create or replace function queryEmpImcome(eno in number)
return number
as --变量
psal emp.sal%type;
pcomm emp.comm%type;
begin
select sal,comm into psal,pcomm from emp where empno=eno;
return (psal+nvl(pcomm,0))*12; end;
*/
@Test
public void testFunction(){
//{?= call <procedure-name>[(<arg1>,<arg2>, ...)]}
//第一个?--> 输出参数,返回值, 第二个 ?-->输入参数
String sql = "{?= call queryEmpImcome(?)}";
Connection conn = null;
CallableStatement call = null; try {
conn = JdbcUtils.getConnection();
call = conn.prepareCall(sql); //注册输出参数
call.registerOutParameter(1, OracleTypes.NUMBER);
//输入参数
call.setInt(2, 7839); //执行
call.execute();
//取出年收入,注意是get 1
double income = call.getDouble(1);
System.err.println("年收入:"+income); } catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.close(call);
JdbcUtils.close(conn);
}
}
}

运行结果:

性能
Statement < preparedStatement < CallableStatement

在Out参数中使用游标

package:程序包

上边的例子的存储过程,输出参数只有三个,如果输出参数有很多,或者输出结果是一个结果集(如查询一个部门中所有员工的信息),此时就需要在out参数中使用游标

例子:查询某个部门所有员工的所有信息

使用PLSQL建包

1,新建包

create or replace package MYPACKAGE as

   type empcursor is ref cursor;

  procedure queryEmpList(dno in number,empList out empcursor);

end MYPACKAGE;

2,新建包体

CREATE OR REPLACE PACKAGE BODY MYPACKAGE AS

  procedure queryEmpList(dno in number,empList out empcursor) AS
BEGIN open empList for select * from emp where deptno=dno; END queryEmpList; END MYPACKAGE;

使用java程序测试:

@Test
public void testCursor(){
String sql = "{call MYPACKAGE.queryEmpList(?,?)}";
Connection conn = null;
CallableStatement call = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection();
call = conn.prepareCall(sql); call.setInt(1, 10);
call.registerOutParameter(2, OracleTypes.CURSOR); //执行
call.execute();
//取出集合,转换为OracleCallableStatement,去除游标
rs = ((OracleCallableStatement)call).getCursor(2);
while(rs.next()){
String name = rs.getString("ename");
String job = rs.getString("job");
double salary = rs.getDouble("sal"); System.err.println("姓名:"+name+",职位:"+job+",薪水:"+salary); } } catch (Exception e) {
e.printStackTrace();
}finally{
JdbcUtils.close(rs);
JdbcUtils.close(call);
JdbcUtils.close(conn);
}
}

光标当ResultSet关闭的时候就关闭了

												

java调用存储过程、存储函数的更多相关文章

  1. Java 调用存储过程、函数

     一.Java调用存储Oracle存储过程 测试用表: --创建用户表 create table USERINFO ( username ) not null, password ) not null ...

  2. java调用存储过程和函数

    以对表test进行增,删,改,查进行说明:1.新建表test create table TEST ( TID NUMBER not null, TNAME VARCHAR2(32), TCODE VA ...

  3. 【转】java调用存储过程和函数

    一.概述 如果想要执行存储过程,我们应该使用 CallableStatement 接口. CallableStatement 接口继承自PreparedStatement 接口.所以CallableS ...

  4. JDBC第二篇--【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】

    这是我JDBC的第一篇 http://blog.csdn.net/hon_3y/article/details/53535798 1.PreparedStatement对象 PreparedState ...

  5. JDBC【PreparedStatment、批处理、处理二进制、自动主键、调用存储过程、函数】

    1.PreparedStatement对象 PreparedStatement对象继承Statement对象,它比Statement对象更强大,使用起来更简单 Statement对象编译SQL语句时, ...

  6. Oracle数据库游标,序列,存储过程,存储函数,触发器

    游标的概念:     游标是SQL的一个内存工作区,由系统或用户以变量的形式定义.游标的作用就是用于临时存储从数据库中提取的数据块.在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理, ...

  7. Oracle学习(十二):存储过程/存储函数

    1.知识点 --第一个存储过程 /* 打印Hello World create [or replace] PROCEDURE 过程名(參数列表) AS PLSQL子程序体: 调用存储过程: 1. ex ...

  8. JDBC(13)—JDBC调用存储过程和函数

    步骤: JDBC调用存储过程和函数 步骤: ①:通过Connection对象的prepareCall()方法创建一个CallableStatement对象的实例,在使用Connection对象的pre ...

  9. Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器

    ---视图 ---视图的概念:视图就是提供一个查询的窗口,来操作数据库中的数据,不存储数据,数据在表中. ---一个由查询语句定义的虚拟表. ---查询语句创建表 create table emp a ...

  10. oracle 存储过程,存储函数,包,

    http://heisetoufa.iteye.com/blog/366957 认识存储过程和函数 存储过程和函数也是一种PL/SQL块,是存入数据库的PL/SQL块.但存储过程和函数不同于已经介绍过 ...

随机推荐

  1. org.hibernate.HibernateException: /hibernate.cfg.xml not found等三个问题

    初次配置hibernate在myeclipse上: 出现三个问题,怎么都不好使,比对代码,没有问题,查看路径还是没有问题: 1.org.hibernate.HibernateException: /h ...

  2. 用node.js写个在Bash上对字符串进行Base64或URL的encode和decode脚本

    一:自己这段时间经常要用到Base64编码和URL编码,写个编译型语言有点麻烦干脆就用node.js弄了个,弄好后在/etc/profile里加上alias就能完成工具的配置,先上代码: functi ...

  3. IntelliJ IDEA 14 Keygen

    package keygen; import java.math.BigInteger; import java.util.Date; import java.util.zip.CRC32; publ ...

  4. python与JavaScript中正则表达式如何转换

    使用python爬取网站数据的时候,总会遇到各种各样的反爬虫策略,有很大一部分都和JavaScript(以下简称为JS) 有关.在破解这些JS代码的过程中,经常会遇到模拟JS正则表达式的情况,因此,今 ...

  5. Watermelon -- codeforces

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=93241#problem/A  (654123) http://codeforces.co ...

  6. hdu 4946 凸包注意重点

    http://acm.hdu.edu.cn/showproblem.php?pid=4946 给你n个点的坐标和速度,如果一个点能够到达无穷远处,且花费的时间是最少的,则此点输出1,否则输出0. 每个 ...

  7. 解决Redis/Codis Connection with master lost(复制超时)问题

    今天在线上环境中遇到了codis-server报警,按照常规处理流程进行处理,报错步骤如下: 首先将codis-slave的rdb文件移除,并重启codis-slave 在codis-dashbord ...

  8. linux系统编程之信号(三):信号安装、signal、kill,arise讲解

    一,信号安装 如果进程要处理某一信号,那么就要在进程中安装该信号.安装信号主要用来确定信号值及进程针对该信号值的动作之间的映射关系,即进程将要处理哪个信号:该信号被传递给进程时,将执行何种操作. li ...

  9. .NET高级代码审计(第二课) Json.Net反序列化漏洞

    0X00 前言 Newtonsoft.Json,这是一个开源的Json.Net库,官方地址:https://www.newtonsoft.com/json ,一个读写Json效率非常高的.Net库,在 ...

  10. eclipse创建Maven工程没有Maven Dependencies

    记一次eclipse创建Maven工程没有Maven Dependencies的坑 Eclipse版本:luna版 maven用的3.5.0 配置本文不提. 这辆天用Eclipse创建maven工程 ...