接着上一篇 JDBC连接Oracle代码案列操作之--Oracle简单数据准备 继续讲
本篇涉及到的是关于Oracle的数据集返回的问题,比如,在MS SQL和MySql中,存储过程中直接可以select*from 表,外部直接调用存储过程就能看到相应的数据集,但是在Oracle中,这样却是不被允许的,为什么不行呢,因为人家是Oracle,规则是他们定的
在Oracle中,通过游标,我们可以拿到一个数据集(select*)的迭代器(个人理解),这个迭代器,可以作为存储过程的返回参数传出去,然后,在Java中调用对应的存储过程,注册并拿到这个返回参数,做循环遍历(next),就可以依次取到each row的column(列)值---> 表的字段值
Oracle中我们不直接定义一个存储过程,我们利用Java中包(Package)和接口(Interface)的思想,在Oracle中,将一个存储过程看做是一个特殊的函数,将这个函数,放在一个包中进行声明,当然,结合上面说的,这个特殊的函数必须要有一个返回参数(out)是游标cursor类型的,这一步过程称作,创建包头;然后,我们需要再定义一个包的包体,去实现包头里面的特殊函数(存储过程),这里面才真真牵扯到游标是如何作用到数据集上的,这一步过程称作创建包体; 类似于Java中,包下面定义一个接口,再定义一个接口的实现类,Oracle存储过程的调用,实际上格式就是这种的 call package.procdure(?,?)
如果上面的笼统阐述,没看懂的话,没关系,下面会结合脚本语句,详详细细的完成一个有参存储过程借助返回参数游标达到数据集返回的效果演示
一、确定select数据集
我们想要从表C里面,查询 id = ?的记录,因此,我们需要写一个存储过程,存储过程的入参是 number类型
二、创建包头,声明一个自己定义的游标类型,和对应的存储过程的原型(参数引用自定义的游标类型)
create or replace package pk_test
as
type curType is ref cursor;
procedure proc_test(c_id in number,curRef out pk_test.curType);
end pk_test;
/
三、创建包体,实现包头里面声明的特殊函数(存储过程)
create or replace package body pk_test
as
procedure proc_test(c_id in number,curRef out pk_test.curType)
as
begin
open curRef for
select*from C where id = c_id;
end proc_test;
end pk_test;
/
四、SQL脚本语句测试特殊函数(存储过程),注意,这个存储过程的调用,需要指明是哪个包下面的
set serveroutput on;
declare
mycur pk_test.curType;
rid number(6);
rname nvarchar2(10);
rsex char(2);
rage integer;
remail varchar2(20);
begin
pk_test.proc_test(5,mycur);
loop fetch mycur into rid,rname,rsex,rage,remail;
exit when mycur%notfound;
dbms_output.put_line('id:'||rid||' 姓名:'||rname||' 性别:'||rsex||' 年龄:'||rage||' 邮箱:'||remail);
end loop;
close mycur;
end;
/
再来一个ID,ID = 1
五、Java调用Oracle存储过程,并获得返回参数(一个游标对象),next()方法遍历对象中的数据集
准备Oracle驱动jar包 ---->下载地址 Oracle11g驱动包
调用demo和注释写的都很详细,一会直接放出demo,下面先放一个项目目录结构,就是一个简单的Java Project
六、查看服务名orcl监听的IP地址
(1)Net Manager管理器查看
服务名orcl对应的host--->192.168.1.83
Oracle监听程序监听的host --->192.168.1.83
(2)本地Oracle安装环境目录中相应的配置文件查看(Net Manager配置后,自动保存)
七、Java调用Oracle存储过程,JDBC代码完整演示和说明
OracleJDBCTest.Java
package com.appleyk.oracle.conn;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import oracle.jdbc.driver.OracleTypes;
public class OracleJDBCTest {
private static String driver = "oracle.jdbc.driver.OracleDriver";
//Oracle JDBC Thin using an SID:
//url格式:jdbc:oracle:thin:@host:port:SID
private static String url ="jdbc:oracle:thin:@192.168.1.83:1521:orcl";
private static String user ="appleyk";
private static String pwd ="sa123" ;
private static Connection conn = null;
public static void main(String[] args){
try {
//1.判断一下驱动类是否存在,不存在做异常处理
Class.forName(driver);
//2.拿到connection
conn = DriverManager.getConnection(url, user, pwd);
//3.准备调用sql语句,"{call 包名.存储过程(?,?....)}"
String callSql = "{call pk_test.proc_test(?,?)}";
//4.创建一个调用存储过程的实例
CallableStatement cStatement = conn.prepareCall(callSql);
//5.给存储过程赋参数(proc_test,有两个参数,一个是输入参数,一个是返回参数,返回的游标正是我们需要的)
//给第一个参数赋值,我们想要获得表C中 id = 4 的记录
//注意参数的位置,不从0开始,下面从游标对象中遍历数据的时候,使用index也不是从0开始
cStatement.setInt(1, 1);
//6.注册一个返回参数,参数位置2,参数类型CURSOR(游标)类型
cStatement.registerOutParameter(2, OracleTypes.CURSOR);
//7.执行存储调用
cStatement.execute();
//8.拿到存储调用实例cStatement里面的返回参数(CURSOR对象)
//注意:返回参数的位置-->parameterIndex = 2
ResultSet rSet = (ResultSet)cStatement.getObject(2);
//9.遍历rSet,首先rSet不等于null,且next()方法有记录
if(!rSet.next()){
System.out.println("查询记录返回为空!");
}
while(rSet !=null & rSet.next()){
int cid = rSet.getInt (1); //字段:id
String cname = rSet.getString (2); // name
String csex = rSet.getString (3); // sex
int cage = rSet.getInt (4); // age
String cemail = rSet.getString(5); // email
System.out.println("ID:"+cid+"\nName:"+cname+"\nSex:"+csex+"\nAge:"
+cage+"\nEmail:"+cemail);
}
//10.关闭相关资源
rSet.close();
cStatement.close();
conn.close();
} catch (ClassNotFoundException e) {
System.err.println("Oracle连接驱动类OracleDriver不存在!");
} catch (SQLException e) {
System.err.println(e.getMessage());
}
}
}
A.对应数据集sql语句 : select*from C where id = 1;
B.对应数据集sql语句 : select*from C where id = 2;