在本系列学习随笔中的第2节我们留下了2个问题,我们现在讨论在out参数中使用光标。
1、要在out参数中使用光标,我们需要申明一个包的结构,包的结构分为包头和包体,包头只负责申明,包体只负责实现。包头、包体也是数据库中的对象,与表是同一级别类型。
应用场景举例:查询某部门所有员工的所有信息
包头:根据以下步骤创建
命名包名:mypackage:
在包中编写我们自己的存储过程或者存储函数:
按下键盘ctrl+s,sql developer将自动存盘并且进行编译:
接下来我们创建包的主体:
将会自动为我们创建要实现的包体部分:
然后我们将包体实现完整:
同样,按下ctrl+s后,将自动帮我们存盘和编译生成相应的包体结构树:
使用desc语句查看包的结构:
2、在应用中访问包中的存储过程,需要带上包的名字
在测试包中添加我们的测试类TestCursor.java
package demo.oracle; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.ResultSet; import org.junit.Test; import demo.utils.JDBCUtils; import oracle.jdbc.OracleCallableStatement; import oracle.jdbc.internal.OracleTypes; public class TestCursor { /** * create or replace PACKAGE MYPACKAGE AS type empcursor is ref cursor; procedure queryEmpList(dno in number,empList out empcursor); END MYPACKAGE; */ @Test public void testCursor(){ //{call <procedure-name>[(<agr1>,<agr2>,...)]} String sql="{call MYPACKAGE.queryEmpList(?,?)}"; Connection conn=null; CallableStatement call=null; ResultSet rs=null; try { //获得数据库连接 conn=JDBCUtils.getConnection(); //根据连接创建statment call=conn.prepareCall(sql); //对in参数赋值 call.setInt(1, 10); //对out参数进行申明 call.registerOutParameter(2, OracleTypes.CURSOR); //执行我们的调用 call.execute(); //取出该部门中所有员工的信息,由于我们当前是Oracle的光标,Oracle的存储过程,所以我们要对call进行转换 rs=((OracleCallableStatement)call).getCursor(2); while(rs.next()){ //取出该员工的员工号、姓名、薪水、职位字段作为示例 int empno = rs.getInt("empno"); String name = rs.getString("ename"); double salary = rs.getDouble("sal"); String job = rs.getString("job"); System.out.println(empno+"\t"+name+"\t"+salary+"\t"+job); } } catch (Exception e) { e.printStackTrace(); }finally { JDBCUtils.release(conn, call, rs); } } }
启动我们的单元测试,运行结果:
总结:存储过程可以实现存储函数所有的能力