【Java EE 学习 29 下】【JDBC编程中操作Oracle数据库】【调用存储过程的方法】

疑问:怎样判断存储过程执行之后返回值是否为空。

一、连接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.运行结果

  

原文地址:https://www.cnblogs.com/kuangdaoyizhimei/p/4754624.html