`
sjsky
  • 浏览: 921696 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JDBC调用存储过程:四种分类详解及实例(Oracle)

    博客分类:
  • J2EE
阅读更多

   blog迁移至 :http://www.micmiu.com

 

本文主要是总结 如何实现 JDBC调用Oracle的存储过程,从以下情况分别介绍:

  • [1]、只有输入IN参数,没有输出OUT参数
  • [2]、既有输入IN参数,也有输出OUT参数,输出是简单值(非列表)
  • [3]、既有输入IN参数,也有输出OUT参数,输出是列表
  • [4]、输入输出参数是同一个(IN OUT)

【准备工作】

  创建一个测试表TMP_MICHAEL ,并插入数据,SQL如下:

create table TMP_MICHAEL
(
  USER_ID    VARCHAR2(20),
  USER_NAME  VARCHAR2(10),
  SALARY     NUMBER(8,2),
  OTHER_INFO VARCHAR2(100)
)

insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)
values ('michael', 'Michael', 5000, 'http://sjsky.iteye.com');
insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)
values ('zhangsan', '张三', 10000, null);
insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)
values ('aoi_sola', '苍井空', 99999.99, 'twitter account');
insert into TMP_MICHAEL (USER_ID, USER_NAME, SALARY, OTHER_INFO)
values ('李四', '李四', 2500, null);

  Oracle jdbc 常量:

    private final static String DB_DRIVER = "oracle.jdbc.driver.OracleDriver";
    private final static String DB_CONNECTION = "jdbc:oracle:thin:@127.0.0.1:1521:Ora11g";
    private final static String DB_NAME = "mytest";
    private final static String DB_PWd = "111111";

 [一]、只有输入IN参数,没有输出OUT参数

 

 

存储过程 TEST_MICHAEL_NOOUT 的相关SQL:

CREATE OR REPLACE PROCEDURE TEST_MICHAEL_NOOUT(P_USERID    IN VARCHAR2,
                                               P_USERNAME  IN VARCHAR2,
                                               P_SALARY    IN NUMBER,
                                               P_OTHERINFO IN VARCHAR2) IS
BEGIN

  INSERT INTO TMP_MICHAEL
    (USER_ID, USER_NAME, SALARY, OTHER_INFO)
  VALUES
    (P_USERID, P_USERNAME, P_SALARY, P_OTHERINFO);

END TEST_MICHAEL_NOOUT;

调用代码如下:

 /**
     * 测试调用存储过程:无返回值
     * @blog http://sjsky.iteye.com
     * @author Michael
     * @throws Exception
     */
    public static void testProcNoOut() throws Exception {
        System.out.println("-------  start 测试调用存储过程:无返回值");
        Connection conn = null;
        CallableStatement callStmt = null;
        try {
            Class.forName(DB_DRIVER);
            conn = DriverManager.getConnection(DB_CONNECTION, DB_NAME, DB_PWd);
            // 存储过程 TEST_MICHAEL_NOOUT 其实是向数据库插入一条数据
            callStmt = conn.prepareCall("{call TEST_MICHAEL_NOOUT(?,?,?,?)}");

            // 参数index从1开始,依次 1,2,3...
            callStmt.setString(1, "jdbc");
            callStmt.setString(2, "JDBC");
            callStmt.setDouble(3, 8000.00);
            callStmt.setString(4, "http://sjsky.iteye.com");
            callStmt.execute();
            System.out.println("-------  Test End.");
        } catch (Exception e) {
            e.printStackTrace(System.out);
        } finally {
            if (null != callStmt) {
                callStmt.close();
            }
            if (null != conn) {
                conn.close();
            }
        }
    }

 运行后查询数据库内容,已经成功插入数据,截图如下:


 

[二]、既有输入IN参数,也有输出OUT参数,输出是简单值(非列表)

 

存储过程 TEST_MICHAEL 的SQL如下:

CREATE OR REPLACE PROCEDURE TEST_MICHAEL(P_USERID IN VARCHAR2,
                                         P_SALARY IN NUMBER,
                                         P_COUNT  OUT NUMBER) IS
  V_SALARY NUMBER := P_SALARY;
BEGIN
  IF V_SALARY IS NULL THEN
    V_SALARY := 0;
  END IF;
  IF P_USERID IS NULL THEN
    SELECT COUNT(*)
      INTO P_COUNT
      FROM TMP_MICHAEL T
     WHERE T.SALARY >= V_SALARY;
  ELSE
    SELECT COUNT(*)
      INTO P_COUNT
      FROM TMP_MICHAEL T
     WHERE T.SALARY >= V_SALARY
       AND T.USER_ID LIKE '%' || P_USERID || '%';
  END IF;
  DBMS_OUTPUT.PUT_LINE('v_count=:' || P_COUNT);
END TEST_MICHAEL;

  调用程序如下:

 /**
     * 测试调用存储过程:返回值是简单值非列表
     * @blog http://sjsky.iteye.com
     * @author Michael
     * @throws Exception
     */
    public static void testProcOutSimple() throws Exception {
        System.out.println("-------  start 测试调用存储过程:返回值是简单值非列表");
        Connection conn = null;
        CallableStatement stmt = null;
        try {
            Class.forName(DB_DRIVER);
            conn = DriverManager.getConnection(DB_CONNECTION, DB_NAME, DB_PWd);

            stmt = conn.prepareCall("{call TEST_MICHAEL(?,?,?)}");

            stmt.setString(1, "");
            stmt.setDouble(2, 3000);

            // out 注册的index 和取值时要对应
            stmt.registerOutParameter(3, Types.INTEGER);
            stmt.execute();

            // getXxx(index)中的index 需要和上面registerOutParameter的index对应
            int i = stmt.getInt(3);
            System.out.println("符号条件的查询结果 count := " + i);
            System.out.println("-------  Test End.");
        } catch (Exception e) {
            e.printStackTrace(System.out);
        } finally {
            if (null != stmt) {
                stmt.close();
            }
            if (null != conn) {
                conn.close();
            }
        }
    }

   测试程序就是查询薪水3000以上人员的数量 ,运行结果如下:

------- start 测试调用存储过程:返回值是简单值非列表
符号条件的查询结果 count := 4
------- Test End.

 

[三]、既有输入IN参数,也有输出OUT参数,输出是列表

  首先需要创建PACKAGE TEST_PKG_CURSOR 的SQL如下:

CREATE OR REPLACE PACKAGE TEST_PKG_CURSOR IS

  -- Author  : MICHAEL  http://sjsky.iteye.com
  TYPE TEST_CURSOR IS REF CURSOR;

END TEST_PKG_CURSOR;

再创建存储过程 TEST_P_OUTRS 的SQL如下:

CREATE OR REPLACE PROCEDURE TEST_P_OUTRS(P_SALARY IN NUMBER,
                                         P_OUTRS  OUT TEST_PKG_CURSOR.TEST_CURSOR) IS
  V_SALARY NUMBER := P_SALARY;
BEGIN
  IF P_SALARY IS NULL THEN
    V_SALARY := 0;
  END IF;
  OPEN P_OUTRS FOR
    SELECT * FROM TMP_MICHAEL T WHERE T.SALARY > V_SALARY;
END TEST_P_OUTRS;

 调用存储过程的代码如下:

 /**
     * 测试调用存储过程:有返回值且返回值为列表的
     * @blog http://sjsky.iteye.com
     * @author Michael
     * @throws Exception
     */
    public static void testProcOutRs() throws Exception {
        System.out.println("-------  start 测试调用存储过程:有返回值且返回值为列表的");
        Connection conn = null;
        CallableStatement stmt = null;
        ResultSet rs = null;
        try {
            Class.forName(DB_DRIVER);
            conn = DriverManager.getConnection(DB_CONNECTION, DB_NAME, DB_PWd);

            stmt = conn.prepareCall("{call TEST_P_OUTRS(?,?)}");

            stmt.setDouble(1, 3000);
            stmt.registerOutParameter(2, OracleTypes.CURSOR);
            stmt.execute();

            // getXxx(index)中的index 需要和上面registerOutParameter的index对应
            rs = (ResultSet) stmt.getObject(2);
            // 获取列名及类型
            int colunmCount = rs.getMetaData().getColumnCount();
            String[] colNameArr = new String[colunmCount];
            String[] colTypeArr = new String[colunmCount];
            for (int i = 0; i < colunmCount; i++) {
                colNameArr[i] = rs.getMetaData().getColumnName(i + 1);
                colTypeArr[i] = rs.getMetaData().getColumnTypeName(i + 1);
                System.out.print(colNameArr[i] + "(" + colTypeArr[i] + ")"
                        + " | ");
            }
            System.out.println();
            while (rs.next()) {
                StringBuffer sb = new StringBuffer();
                for (int i = 0; i < colunmCount; i++) {
                    sb.append(rs.getString(i + 1) + " | ");
                }
                System.out.println(sb);
            }
            System.out.println("------- Test Proc Out is ResultSet end. ");

        } catch (Exception e) {
            e.printStackTrace(System.out);
        } finally {
            if (null != rs) {
                rs.close();
            }
            if (null != stmt) {
                stmt.close();
            }
            if (null != conn) {
                conn.close();
            }
        }
    }

 运行结果如下:

------- start 测试调用存储过程:有返回值且返回值为列表的
USER_ID(VARCHAR2) | USER_NAME(VARCHAR2) | SALARY(NUMBER) | OTHER_INFO(VARCHAR2) |
michael | Michael | 5000 | null |
zhangsan | 张三 | 10000 | null |
aoi_sola | 苍井空 | 99999.99 | null |
jdbc | JDBC | 8000 | http://sjsky.iteye.com |
------- Test Proc Out is ResultSet end.
 

[四]、输入输出参数是同一个(IN OUT)

 

创建存储过程TEST_P_INOUT 的SQL如下:

CREATE OR REPLACE PROCEDURE TEST_P_INOUT(P_USERID IN VARCHAR2,
                                         P_NUM    IN OUT NUMBER) IS
  V_COUNT  NUMBER;
  V_SALARY NUMBER := P_NUM;
BEGIN
  IF V_SALARY IS NULL THEN
    V_SALARY := 0;
  END IF;

  SELECT COUNT(*)
    INTO V_COUNT
    FROM TMP_MICHAEL
   WHERE USER_ID LIKE '%' || P_USERID || '%'
     AND SALARY >= V_SALARY;
  P_NUM := V_COUNT;
END TEST_P_INOUT;

 调用存储过程的代码:

/**
     * 测试调用存储过程: INOUT同一个参数:
     * @blog http://sjsky.iteye.com
     * @author Michael
     * @throws Exception
     */
    public static void testProcInOut() throws Exception {
        System.out.println("-------  start 测试调用存储过程:INOUT同一个参数");
        Connection conn = null;
        CallableStatement stmt = null;
        try {
            Class.forName(DB_DRIVER);
            conn = DriverManager.getConnection(DB_CONNECTION, DB_NAME, DB_PWd);

            stmt = conn.prepareCall("{call TEST_P_INOUT(?,?)}");

            stmt.setString(1, "michael");
            stmt.setDouble(2, 3000);

            // 注意此次注册out 的index 和上面的in 参数index 相同
            stmt.registerOutParameter(2, Types.INTEGER);
            stmt.execute();

            // getXxx(index)中的index 需要和上面registerOutParameter的index对应
            int count = stmt.getInt(2);
            System.out.println("符号条件的查询结果 count := " + count);
            System.out.println("-------  Test End.");
        } catch (Exception e) {
            e.printStackTrace(System.out);
        } finally {
            if (null != stmt) {
                stmt.close();
            }
            if (null != conn) {
                conn.close();
            }
        }
    }

 运行结果如下:

------- start 测试调用存储过程:INOUT同一个参数
符号条件的查询结果 count := 1
------- Test End.

 

到处基本介绍已经结束了,希望能给大家有所帮助。

 

 

本文连接:http://sjsky.iteye.com/blog/1246657

 

 

转载请注明来自:Michael's blog @ http://sjsky.iteye.com



----------------------------- 分 ------------------------------ 隔 ------------------------------ 线 ------------------------------

 

 

 

 

  • 大小: 12 KB
3
3
分享到:
评论
6 楼 1028546747 2012-05-22  
赞一个
5 楼 xwl1991 2011-11-11  
学习学习……
4 楼 sjsky 2011-11-10  
liupopo 写道
呵呵,再写一个:
[5] 既有输入IN参数,也有输出OUT参数,输出是简单值 和 列表
这样的例子吧。

比如做分页查询,需要同时获得 总记录数 和 当前页的记录列表

有意思,不过这个和之前的介绍的几种情况结合一下就可以了,现在网上这种分页的应该很多的
3 楼 liupopo 2011-11-10  
呵呵,再写一个:
[5] 既有输入IN参数,也有输出OUT参数,输出是简单值 和 列表
这样的例子吧。

比如做分页查询,需要同时获得 总记录数 和 当前页的记录列表
2 楼 sjsky 2011-11-10  
greatwqs 写道
写的漂亮 

谢谢兄弟的 顶 
1 楼 greatwqs 2011-11-10  
写的漂亮 

相关推荐

    java调用存储过程实例

    ### Java调用存储过程实例:详解 #### 存储过程简介 存储过程是一种在数据库中编写的SQL程序,可以接受输入参数,执行一系列操作,并返回结果或输出参数。它们可以提高应用程序的性能、安全性和复用性。在Oracle...

    jdbc调用存储过程

    ### JDBC调用存储过程知识点详解 #### 一、概述 在数据库应用开发中,存储过程是一种重要的编程元素,它能够封装一系列SQL语句并作为一个独立的单元执行,从而提高代码的复用性和性能。JDBC(Java Database ...

    oracle的一个简单存储过程实例

    Oracle存储过程是数据库管理系统中的一种重要特性,它允许开发者编写包含一系列SQL语句和PL/SQL块的可重用代码段。在这个“Oracle的一个简单存储过程实例”中,我们可以看到如何在Oracle环境中创建、调用和管理存储...

    oracle 存储过程 函数 dblink

    ### Oracle存储过程、函数与DBLink详解 #### 一、Oracle存储过程简介 在Oracle数据库中,存储过程是一种预编译好的SQL代码集合,它可以接受输入参数、返回单个值或多个值,并能够执行复杂的数据库操作。存储过程...

    oracle 存储过程实例

    ### Oracle存储过程实例详解 #### 一、存储过程概述 在Oracle数据库中,存储过程是一种预编译的SQL代码块,它可以包含复杂的逻辑处理,并且能够接收参数、执行操作、返回结果。存储过程的主要优点包括提高性能...

    Oracle存储过程学习经典[语法+实例+调用].

    ### Oracle存储过程学习经典知识点详解 #### 一、Oracle存储过程基础知识 **1. 商业规则与业务逻辑的实现** - **定义**: 存储过程是存储在Oracle数据库中的可执行程序单元,通常用于封装复杂的业务逻辑或数据...

    oracle 调用webservice

    Oracle 调用 Webservice 实现详解 本文将详细介绍 Oracle 调用 Webservice 的实现过程,包括 Webservice 的基本概念、 Java 编写简单的 WebService 实例、Oracle 服务器端配置、加载 JAR 包、测试调用 ...

    存储过程学习经典[语法+实例+调用]

    **Oracle存储过程**是一种可以在Oracle数据库中存储并可被多次调用的程序单元。它可以包含一系列SQL语句和控制流语句,用于执行复杂的操作。存储过程的主要优势在于它们能够提高应用性能、减少网络流量,并提供更高...

    oracle存储过程学习经典[语法+实例+调用]

    ### Oracle存储过程学习经典知识点详解 #### 一、Oracle存储过程概述 - **定义**: 存储过程是在数据库中预编译并存储的一段SQL或PL/SQL代码块,它可以包含复杂的逻辑处理,用于实现特定的功能。存储过程提高了代码...

    Oracle JDBC连接字符串

    ### Oracle JDBC连接字符串详解 在Java开发环境中,与Oracle数据库进行交互时,通常会使用Java Database Connectivity (JDBC)技术来实现。本文将详细介绍如何通过JDBC连接Oracle数据库,并解释连接字符串及相关配置...

    java 调用存储过程列子

    ### Java调用Oracle存储过程详解 #### 一、概述 在Java编程中,尤其是在与数据库交互时,存储过程是一个非常重要的概念。通过调用数据库中的存储过程,可以提高应用程序的性能,并增强数据处理的安全性和复杂性。...

    JDBC连接MySQL 实例

    **JDBC连接MySQL实例详解** Java Database Connectivity (JDBC) 是Java编程语言中用于与数据库交互的一种接口标准,由Sun Microsystems公司(现为Oracle公司)开发。它为Java程序员提供了标准化的方法来创建、执行...

    java连接oracle实例

    ### Java连接Oracle数据库实例详解 #### 一、引言 在现代软件开发中,Java作为最流行的编程语言之一,广泛应用于各种应用场景,特别是在企业级应用领域。而在这些应用中,数据库操作是必不可少的一部分。Oracle...

    jdbc 知识点详解

    【JDBC知识点详解】 JDBC(Java Database Connectivity)是Java编程语言中用于规范客户端程序如何访问数据库的应用程序接口,它是由Sun Microsystems公司定义的一套标准API,使得Java开发者能够使用相同的代码来与...

    数据库连接JDBC详解

    ### 数据库连接JDBC详解 #### 一、JDBC基本概念及重要性 JDBC (Java Database Connectivity) 是 Sun 公司(现已被 Oracle 收购)推出的一种标准技术,它属于 JavaSE 范畴,主要用于实现 Java 应用程序与各种不同...

    JDBC技术全面详解

    1. **JDBC驱动**: JDBC驱动是Java与数据库之间的桥梁,分为四种类型:Type 1(JDBC-ODBC桥接)、Type 2(部分Java驱动)、Type 3(网络协议驱动)和Type 4(纯Java驱动)。 2. **连接数据库**: 使用`DriverManager....

    java连接Oracle数据库详解

    ### Java连接Oracle数据库详解 #### 一、引言 在现代软件开发中,Java与数据库的结合是非常常见的技术栈之一。对于使用Java进行后端开发的程序员来说,掌握如何使用Java来连接并操作Oracle数据库是一项必备技能。...

    详解java调用存储过程并封装成map

    "Java调用存储过程并封装成Map" ...本文详细介绍了Java调用存储过程并封装成Map对象的步骤和实例代码,通过本文,我们可以轻松地实现Java调用存储过程并将结果封装成Map对象,以便于后续的数据处理。

    JDBC连接数据库实例+附源码

    **JDBC连接数据库实例详解** Java Database Connectivity (JDBC) 是Java编程语言中用于规范客户端程序如何访问数据库的应用程序接口(API),它为开发者提供了一种标准的、面向对象的方式来访问和操作各种数据库系统...

Global site tag (gtag.js) - Google Analytics