JDBC实现调用Oracle存储过程

2018-06-10 22:25:19 7137

1.关于JDBC 
(1)什么是JDBC? 
JDBC的全称是Java Database Connectivity。主要有三个功能: 
a.建立与数据库的连接和访问任意表格数据源。 
b.发送一个SQL声明。 
c.处理结果。

(2)连接数据库的前提 
a.安装jdk。 
b.安装数据库。 
c.下载对应数据库的驱动。

(3)数据库驱动的类型 
a.驱动实现JDBC API作为其他数据访问API的一种映射,类似ODBC(Open Database Connectivity 开放数据库连接)。这种类型的驱动通常依赖于本地库,移植性受到很大的限制。如JDBC-ODBC桥接。注意:JDBC-ODBC桥接被认为是传统的解决方案。它不支持Oracle数据库。使用这个驱动最好在您的DBMS(数据库管理系统)不提供java的JDBC驱动的情况下。 
b.驱动程序编写部分是Java程序语言,部分是本地代码。这些驱动程序使用本地客户端库明确它们连接的数据源是哪个。而且,因为本地代码,移植性也受到了限制。如Oracle的OCI(Oracle Call Interface Oracle回调接口)客户端。 
c.使用纯java的客户机,使用与数据库无关的协议和中间服务器通信。中间件服务器将主机的请求和数据源进行通信。 
d.使用纯java和实现了网络协议的驱动程序来明确数据源。客户端直接和数据源连接。 
(这个大家可以看看Java关于JDBC的文档。)

2.先在数据库创建一个存储过程, 
(1)先创建包

CREATE OR REPLACE PACKAGE LFF_TEST_PACKAGE
is
PROCEDURE LFF_TEST_PROCEDURE(id in number,org out varchar2,po_fhz out varchar2,po_msg out varchar2);
end LFF_TEST_PACKAGE;1
2
3
4
说明:id是number类型的需要传入的参数,org,po_phz,po_msg是varchar2类型的传出的参数。 
(2)创建包的实体

create or replace package body LFF_TEST_PACKAGE as
  PROCEDURE LFF_TEST_PROCEDURE(id in number,org out varchar2,po_fhz out varchar2,po_msg out varchar2)
  as
    --定义其他需要使用的变量,需要指定类型及其大小如 username varchar2(20) 而存储过程名称括号里面的输入和输出参数是没有指定类型大小的
    begin
      --select * into org from XX where xxx = id;
      org := 'aaa';
      po_fhz := '1';
      po_msg := '调用成功';
    exception
    when others then
      po_fhz := '-1';
      po_msg := '调用不成功';
  end;
end LFF_TEST_PACKAGE;

注意:exception表示出现错误时的处理。when others子句用于捕获命名系统异常和命名的程序员定义异常未处理的所有其余异常。我自己的理解就是相当于java中的try{}catch(Exception e){}中的exception。

3.利用JDBC调用数据库的存储过程。 
总的来说,执行任何JDBC的SQL声明,有以下几个步骤: 
(1)建立连接。建立的数据连接可以是DBMS,传统的文件系统,或者使用相应的JDBC驱动程序的其他数据源。在Java API中对应的是Connection类。 
(2)创建声明。在Java API中有三种类型的声明: 
a.Statement:用于不带参数实现简单SQL声明。 
b.PreparedStatement:(继承Statement),用于可以带有输入参数的预编译SQL声明。 
c.CallableStatement:(继承PreparedStatement),用于执行带有输入输出参数的存储过程。

(3)执行语句。Java API中有三种执行方法。 
a.execute:使用这个方法可以返回一个或更多个结果集对象。 
b.executeQuery:返回一个结果集。用于查询语句。 
c.executeUpdate:返回受到影响的记录的数目。这个方法用于插入insert,删除delete,或是更新update。

(4)处理结果集对象。通过光标处理ResultSet对象。这个光标不是数据库中的光标。这个光标是一个指针指向结果集对象中的某一行数据。最初,这个光标位于第一行数据的前面,你可以使用在结果集ResultSet对象中定义的各种各样的方法移动光标。

(5)关闭连接。无论是否抛出异常,在finally中调用close方法。根据先打开后关闭的原则。

/**
 * @date 2017-6-6
 * @author liufeifei
 * @description 测试调用数据库的存储过程
 */
public class TestProcedure {

    public static void main(String[] args) {
        //数据库驱动的名称
        String driver = "oracle.jdbc.OracleDriver";
        //访问数据库路径 localhost表示本机(127.0.0.1),xxx表示数据库名称
        String url = "jdbc:oracle:thin:@localhost:1521:xxx";
        //用户名
        String username = "kfxx";
        //密码
        String password = "kfxx";
        Connection conn = null;
        CallableStatement statement = null;
        try {
            //加载驱动
            Class.forName(driver);
            //连接
            conn = DriverManager.getConnection(url, username, password);
            //请求的存储过程(包名.存储过程名称,四个?表示参数)
            String sql = "{call LFF_TEST_PACKAGE.LFF_TEST_PROCEDURE(?,?,?,?)}";
            statement = conn.prepareCall(sql);
            //传入的参数
            statement.setInt(1,21);
            //返回的参数(oracle.jdbc.OracleTypes.VARCHAR表示返回参数类型)
            statement.registerOutParameter(2,oracle.jdbc.OracleTypes.VARCHAR);
            statement.registerOutParameter(3,oracle.jdbc.OracleTypes.VARCHAR);
            statement.registerOutParameter(4,oracle.jdbc.OracleTypes.VARCHAR);
            //执行
            statement.execute();
            //拿到返回的值,我的存储过程的参数1是传入参数,2,3,4是传出参数
            System.out.println(statement.getString(2) + " "+ statement.getString(3) + " "+ statement.getString(4));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            try { 
                  //关闭连接
                  if(statement != null){
                        statement.close();
                  }
                  if(conn != null){
                      conn.close();
                  }
            } catch (SQLException ex1) {
            }
        }
    }
}

另外,Statement和PreparedStatement的使用: 
(1)这三个都是接口Interface。大家可以去看看JDK的源码

public interface Statement extends Wrapper {}
public interface PreparedStatement extends Statement {}
public interface CallableStatement extends PreparedStatement {}1
2
3
Statement是用来执行不带参数的SQL语句。

Connection conn = null;
ResultSet rs = null;
Statement statement = null;
try {
    //加载
    Class.forName(driver);
    //连接
    conn = DriverManager.getConnection(url, username, password);
    //设置查询语句
    statement = conn.createStatement();
    statement.execute("select * from emp");
    //执行查询
    rs = statement.getResultSet();
    while(rs.next()){              
      System.out.println(rs.getObject(2)+"==>"+rs.getObject(1));
    }
} catch (ClassNotFoundException e) {
    e.printStackTrace();
}

PreparedStatement是用来执行带输入参数的SQL语句。

Connection conn = null;
ResultSet rs = null;
PreparedStatement statement = null;
try {
      //加载
      Class.forName(driver);
      //连接
      conn = DriverManager.getConnection(url, username,password);
      //设置查询语句
      statement = conn.prepareStatement("select * from emp where ename like ?");
      //设置参数
      statement.setString(1,"%S%");
      //执行查询
      rs = statement.executeQuery();
      while(rs.next()){
          System.out.println(rs.getObject(2)+"==>"+rs.getObject(1));
      }
}catch(){  
}


提交成功!非常感谢您的反馈,我们会继续努力做到更好!

这条文档是否有帮助解决问题?

非常抱歉未能帮助到您。为了给您提供更好的服务,我们很需要您进一步的反馈信息:

在文档使用中是否遇到以下问题: