疑问:怎样判断存储过程执行之后返回值是否为空。
一、连接oracle数据库
1.需要的jar包:在安装的oracle中就有,所以不需要到官网下载,我的oracle11g下:D:appkdyzmproduct11.2.0dbhome_1jdbclib,文件夹中有若干.jar文件,选择ojdbc6.jar即可。
2.连接oracle
驱动位置:oracle.jdbc.OracleDriver
url写法:jdbc:oracle:thin:@localhost:1521:orcl
3.JDBCUtils
package com.kdyzm.dbutils; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class JDBCUtils { private static final String driver="oracle.jdbc.driver.OracleDriver"; private static final String url="jdbc:oracle:thin:@localhost:1521:orcl"; private static final String username="scott"; private static final String password="tiger"; static { try { Class.forName(driver); } catch (ClassNotFoundException e) { throw new ExceptionInInitializerError("Oracle数据库连接初始化失败!"); } } //获取Connection连接的方法 public static Connection getConnection() { Connection conn=null; try { conn=DriverManager.getConnection(url,username,password); } catch (SQLException e) { e.printStackTrace(); } return conn; } //释放资源的标准方法 public static void free(Connection conn,Statement st,ResultSet rs) { if(rs!=null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); }finally{ rs=null; if(st!=null) { try { st.close(); } catch (SQLException e) { e.printStackTrace(); }finally{ st=null; if(conn!=null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); }finally{ conn=null; } } } } } } } }
4.测试连接
package com.kdyzm.test; import java.sql.Connection; import com.kdyzm.dbutils.JDBCUtils; /* * 测试与Oracle数据库之间的连接 */ public class TestConnection { public static void main(String[] args) { Connection conn=JDBCUtils.getConnection(); System.out.println(conn); JDBCUtils.free(conn, null, null); } }
二、调用存储过程
1.使用CallableStatement标准接口。
java.sql.Statement
|--java.sql.CallableStatement
创建存储过程:
create or replace procedure searchEmpByEmpno(pempno in NUMBER,pename out varchar2, pjob out varchar2,psal out number) as begin select ename,job,sal into pename,pjob,psal from emp where empno=pempno; end;
2.调用存储过程
package com.kdyzm.test; /* * 测试oracle调用存储过程,并得到返回值。 */ import java.sql.CallableStatement; import java.sql.Connection; import java.sql.ResultSet; import oracle.jdbc.OracleTypes; import org.junit.Test; import com.kdyzm.dbutils.JDBCUtils; public class TestProcedure { @Test public void testProcedure() { Connection conn=null; ResultSet rs=null; CallableStatement cs=null; //SQL语句的形式:{call <procedure-name>[(<arg1>,<arg2>, ...)]} String sql="{call searchEmpByEmpno(?,?,?,?)}";//这里的存储过程拥有四个参数,第一个是in类型的,其余的是out类型的。 try { conn=JDBCUtils.getConnection(); cs=conn.prepareCall(sql); //得到CallableStatement对象 cs.setInt(1, 7566); //设置in值 //注册三个输出值 cs.registerOutParameter(2, OracleTypes.VARCHAR); cs.registerOutParameter(3, OracleTypes.VARCHAR); cs.registerOutParameter(4, OracleTypes.DOUBLE); //执行存储过程 cs.execute(); //得到返回结果 String ename=cs.getString(2); String job=cs.getString(3); double sal=cs.getDouble(4); System.out.println(ename+" 的工作是: "+job); System.out.println(ename+" 的薪水是: "+sal); } catch(Exception e) { e.printStackTrace(); } finally{ JDBCUtils.free(conn, cs, rs); } } }
三、调用存储函数
1.本来没有什么不同之处,但这里由于任性使然,故展示一二,创建存储函数
create or replace function myfun(fempno in number) return VARCHAR2 as fename VARCHAR2(20); begin select ename into fename from emp where empno=fempno; return fename; end;
2.调用存储函数
package com.kdyzm.test; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.ResultSet; import oracle.jdbc.OracleTypes; import com.kdyzm.dbutils.JDBCUtils; /* *测试调用存储函数。 */ public class TestFunction { public static void main(String[] args) { Connection conn=null; ResultSet rs=null; CallableStatement cs=null; // {?= call <procedure-name>[(<arg1>,<arg2>, ...)]} String sql="{?=call myfun(?)}"; try { conn=JDBCUtils.getConnection(); cs=conn.prepareCall(sql); cs.registerOutParameter(1, OracleTypes.VARCHAR); cs.setInt(2, 7521); cs.execute(); String ename=cs.getString(1); System.out.println("查询结果为:"+ename); } catch(Exception e) { e.printStackTrace(); } finally{ JDBCUtils.free(conn, cs, rs); } } }
三、调用带有游标返回值的存储过程
1.首先创建存储过程,这里需要使用包
(1)声明包
--声明包 CREATE OR REPLACE PACKAGE MYPACKAGE AS type empcursor is REF CURSOR; PROCEDURE queryEmpList(pempno in NUMBER,empList out empcursor); END MYPACKAGE;
(2)实现包体
CREATE OR REPLACE PACKAGE BODY MYPACKAGE AS PROCEDURE queryEmpList(pempno in NUMBER,empList out empcursor) AS BEGIN open empList for select * from emp where pempno=empno; END queryEmpList; END MYPACKAGE;
(3)PL/SQL匿名块测试
--测试带有游标的out参数。 set serveroutput on; declare pempno number; empList mypackage.empcursor; empRow emp%rowtype; begin pempno:=7369; mypackage.queryemplist(pempno,empList); --open emplist;--注意一定不要再次open,因为游标只能打开一次,否则会报错。 loop fetch emplist into empRow; exit when emplist%notfound; dbms_output.put_line(empRow.ename||'的工资是:'||empRow.sal); end loop; null; close emplist; end; /
2.调用存储过程
package com.kdyzm.test; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.ResultSet; import oracle.jdbc.OracleTypes; import oracle.jdbc.OracleCallableStatement; import com.kdyzm.dbutils.JDBCUtils; /* * 测试带有游标返回值的存储过程 * @author kdyzm * */ public class TestProcedureWithCursor { public static void main(String[] args) { Connection conn=null; CallableStatement cs=null; ResultSet rs=null; String sql="{call mypackage.queryemplist(?,?)}"; try { conn=JDBCUtils.getConnection(); cs=conn.prepareCall(sql); cs.setInt(1, 7521); cs.registerOutParameter(2, OracleTypes.CURSOR); cs.execute(); OracleCallableStatement ocs=(OracleCallableStatement)cs; rs=ocs.getCursor(2); while(rs.next()) { System.out.print(rs.getInt("empno")+" "); System.out.print(rs.getString("ename")+" "); System.out.print(rs.getString("JOB")+" "); System.out.print(rs.getInt("MGR")+" "); System.out.print(rs.getDate("HIREDATE")+" "); System.out.print(rs.getDouble("SAL")+" "); System.out.print(rs.getInt("COMM")+" "); System.out.print(rs.getInt("DEPTNO")+" "); System.out.println(); } } catch(Exception e) { e.printStackTrace(); } finally{ JDBCUtils.free(conn, cs, rs); } } }
3.运行结果