`
zhang_yingjie
  • 浏览: 111818 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

ORACLE存储过程使用数组参数

    博客分类:
  • java
阅读更多
http://blog.csdn.net/louie520/archive/2008/11/18/3326892.aspx,这是原文的地址。

环境:Eclipse+Oracle9.0.2+Tomcat5.5

功能:采用存储过程、type组合来实现批量入库,以节省系统开销,提高效率。

    *

      sql脚本+测试代码:
    * 1)create or replace type t_cableLine_point as object
      (
        ID          NUMBER(10),
        CABLELINEID NUMBER(10),
        ROADPOINTID NUMBER(10),
        ORDERNUM    NUMBER(10),
        REMARK      NUMBER(10)
      )
    * 2)CREATE OR REPLACE TYPE ARRAY_cableLine_point AS table OF t_cableLine_point
    * 3)create table RSC_CABLELINE_POINT
      (
        ID          NUMBER(10) not null,
        CABLELINEID NUMBER(10) not null,
        ROADPOINTID NUMBER(10) not null,
        ORDERNUM    NUMBER(10),
        REMARK      NUMBER(10)
      )
    * 4)create or replace procedure batch_cableline_point(i_object in ARRAY_cableLine_point) is
      begin
        insert into RSC_CABLELINE_POINT
          (ID, CABLELINEID, ROADPOINTID, ORDERNUM, REMARK)
          select ID, CABLELINEID, ROADPOINTID, ORDERNUM, REMARK
            from the (select cast(i_object as ARRAY_cableLine_point) from dual);
      end batch_cableline_point;
    * 5)测试代码:
         1. public class Test {
         2.
         3.     public static void main(String[] args){
         4.         try{
         5.            Class.forName("oracle.jdbc.driver.OracleDriver");
         6.            String url="jdbc:oracle:thin:@192.168.1.2:1521:***";
         7.            Connection con = DriverManager.getConnection(url, "***","***");
         8.            PreparedStatement  pstmt = null;
         9.            String sql = "{call batch_cableline_point(?)}";
        10.           
        11.            pstmt = con.prepareCall(sql);
        12.            Object[][]  object1=new Object[10][5];
        13.            int max = 3615142;//由于表有索引
        14.           for ( int i=0;i<10;i++){
        15.            object1[i][0]=++max;
        16.            object1[i][1]=158870593;
        17.            object1[i][2]= 333;
        18.            object1[i][3]= 444;
        19.            object1[i][4]= 555;
        20.           } 
        21.           
        22.            oracle.sql.ArrayDescriptor desc = oracle.sql.ArrayDescriptor.createDescriptor("ARRAY_CABLELINE_POINT",con);
        23.            oracle.sql.ARRAY array = new oracle.sql.ARRAY(desc,con,object1);
        24.          
        25.            pstmt.setArray(1, array);
        26.            pstmt.executeUpdate();
        27.         } catch (Exception e) {
        28.            e.printStackTrace();
        29.         }
        30.     }
        31. }
  32.
      备注:如果在入库的过程中发现字符串的值没有入进去,请检查有没有加载该类库nls_charset12.jar
      
    * 该文章是参考“风雪”文章后个人试验的存档。
    *
    * 其他参考:(引用2008-5-24 04:49 Aowken)
    * Tomcat+Oracle调用存储过程郁闷之旅

      今天在改公司管理系统的时候,因为某个功能需要使用数组类型作为IN参数调用存储过程,看了看文档发现有Varray、nested table,但Varray有个最多数量的限制,也只好用nested table了,于是引发一连串的问题。
      环境:
      java version "1.6.0_05"
      Java(TM) SE Runtime Environment (build 1.6.0_05-b13)
      Java HotSpot(TM) Client VM (build 10.0-b19, mixed mode, sharing)

      apache-tomcat-6.0.16

      Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
      PL/SQL Release 9.2.0.1.0 - Production
      CORE 9.2.0.1.0 Production
      TNS for 32-bit Windows: Version 9.2.0.1.0 - Production
      NLSRTL Version 9.2.0.1.0 - Production
      本来对Java这种据说很先进的东西就懵懵懂懂,索性就真的以为他非常牛X。使用几维数组作为参数调用存储过程还不是跟Set个String一样那么简单,但其实我错了,所以我也对java很失望,他远不如想象中那么XX。
      Object arrInt[] = {0,1,2,3,4,5,6};
      callStmt.SetObject(1, arrInt, Types.ARRAY);
      要是想像上面这样操作他就会抛个java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to oracle.sql.ARRAY,于是我知道java他不会自己转,非得人工干预。但我突然发现自己很愚蠢,我都没告诉他procedure参数的类型,即使可以转过去又有个P用,百度了一下才知道得用下面的法子。
      import oracle.sql.ARRAY;
      import oracle.sql.ArrayDescriptor;

      Connnection conn = DBConnManager.getConnection();
      callStmt = conn.prepareCall(sql);
      ArrayDescriptor arrDesc = ArrayDescriptor.createDescriptor("dbms_sql.Varchar2_Table", conn);
      ARRAY arr = new ARRAY(arrDesc, conn, arrInt);
      执行一下,结果异常。我靠数据库里能用dbms_sql.Varchar2_Table声明,他居然 java.sql.SQLException: 无效的名称模式: DBMS_SQL.VARCHAR2_TABLE。我心想是不是得写成SYS.dbms_sql.Varchar2_Table,结果还是一样。再百度,人们说这样不行,原因...不知道,但必须得自己定义类型才可以。于是我不得不
      create type numbertable as table of number;

      ArrayDescriptor arrDesc = ArrayDescriptor.createDescriptor("numbertable", conn);
      ARRAY arr = new ARRAY(arrDesc, conn, arrInt);
      结果又来了个java.sql.SQLException: 无效的名称模式: baby.numbertable。我无语还得百度!@#¥%....N久无果!但我发别人的码的代码里这个类型都是大写,于是我也写成 NUMBERTABLE。哈哈,果然不出那个异常了。但他NND又蹦个java.lang.ClassCastException: org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper cannot be cast to oracle.jdbc.OracleConnection出来。这下郁闷了,莫非从DBCP拿出来的Connection跟 OracleConnection不一样。晕了,别介呀,我对java不懂!又search了半天,发现了一个UnWrapper,本以为能把这个 Wrapper给干掉的,但搞了半天没搞明白。过了XX时间,不知道是在哪国网站上看到有人
      ArrayDescriptor arrDesc = ArrayDescriptor.createDescriptor("NUMBERTABLE", ((DelegatingConnection)conn).getDelegate()));
      他们用着都好用,到我这((DelegatingConnection)conn).getDelegate()出来的Connection是个null,很郁闷。后来又看到
      public static Connection getNativeConnection(Connection con) throws SQLException {
        if (con instanceof DelegatingConnection) {
         Connection nativeCon = ((DelegatingConnection) con).getInnermostDelegate();
      //   For some reason, the innermost delegate can be null: not for a
      //   Statement's Connection but for the Connection handle returned by the pool.
      //   We'll fall back to the MetaData's Connection in this case, which is
      //   a native unwrapped Connection with Commons DBCP 1.1.
         return (nativeCon != null ? nativeCon : con.getMetaData().getConnection());
        }
        return con;
      }
      可((DelegatingConnection) con).getInnermostDelegate();依然是null但con.getMetaData().getConnection());得到了一个OracleConnection,debug时看着eclipse variables的窗口心中一阵暗喜,该OK了吧!

      哎,事实上最近一段时间总是事与愿违,执行-又异常了!郁闷,一次比一次郁闷,一次比一次怪异!
      java.lang.ClassCastException: oracle.jdbc.driver.OracleConnection cannot be cast to oracle.jdbc.OracleConnection 由于字符串太长搜都搜不到,想了好久,尝试着各种各样的方法!终于有一个次把tomcat/lib目录classes12.jar删掉,没有异常,一切 OK!但后来把classes12.jar又仍进去了,还正常的,代码没有一点变化!很是郁闷,但既然问题没了,也就懒得看了!

      最后的代码:
      -----------------------------------------------------------------------------------
      public static Connection getConnection() {
        Connection con = null;
        try {
         Context ic = new InitialContext();
         DataSource ds = (DataSource) ic.lookup("java:comp/env/jdbc/yoyo");
         con = ds.getConnection();
        } catch (Exception e) {
         System.out.println("**** error DataSource");
        }
        return con;
      }
      -----------------------------------------------------------------------------------
      import java.sql.Connection;
      import java.sql.PreparedStatement;
      import java.sql.CallableStatement;
      import java.sql.ResultSet;
      import java.sql.SQLException;
      import java.sql.Types;
      import java.util.ArrayList;
      import oracle.sql.ARRAY;
      import oracle.sql.ArrayDescriptor;
      import org.apache.tomcat.dbcp.dbcp.DelegatingConnection;
      public class BussinessLog {
      public static ArrayList CancelLog(String sLoginUser, Object[] arrLogID)
      {
        ArrayList arrList = new ArrayList();
        Connection conn = null;
        CallableStatement callStmt = null;
        String sql = null;
        ArrayDescriptor arrDesc = null;
       
        try
        {
         conn = DbConnectionManager.getConnection();
         sql = "{call P_CanceltLog(?,?,?,?)}";  
         callStmt = conn.prepareCall(sql);
         arrDesc = ArrayDescriptor.createDescriptor("NUMBERTABLE", getNativeConnection(conn));
         ARRAY arr = new ARRAY(arrDesc, getNativeConnection(conn), arrLogID);
         callStmt.setString(1, sLoginUser);
         callStmt.setObject(2, arr, Types.ARRAY);
         callStmt.registerOutParameter(3, Types.VARCHAR);
         callStmt.registerOutParameter(4, Types.INTEGER);
         callStmt.execute();
        
         arrList.add(callStmt.getInt(4));
         arrList.add(callStmt.getString(3));
         return arrList;
        } catch (Exception e) {
         System.out.println(e.toString());
        } finally {
         DbAction.clear(conn, callStmt);
        }
        return arrList;
      }

      public static Connection getNativeConnection(Connection con) throws SQLException {
        if (con instanceof DelegatingConnection) {
         Connection nativeCon = ((DelegatingConnection) con).getInnermostDelegate();
      //   For some reason, the innermost delegate can be null: not for a
      //   Statement's Connection but for the Connection handle returned by the pool.
      //   We'll fall back to the MetaData's Connection in this case, which is
      //   a native unwrapped Connection with Commons DBCP 1.1.
         return (nativeCon != null ? nativeCon : con.getMetaData().getConnection());
        }
        return con;
      }
      }
      -----------------------------------------------------------------------------------
      A. 在这之前我还下载了最新的commons-dbcp-1.2.2.jar,但使用里面DelegatingConnection时,con instanceof DelegatingConnection是false,看来tomcat里出来的Connection就的配Tomcat\lib\tomcat- dbcp.jar里的DelegatingConnection,还真是什么枪打什么鸟。

      B.偶尔发现 ((DelegatingConnection) con).getInnermostDelegate();之所以返回null是因为tomcat里Context.Resource的 accessToUnderlyingConnectionAllowed参数默认为false所致,被设置成true之后是可以取到 OracleConnection的.
分享到:
评论

相关推荐

    Spring访问传入数组参数的Oracle存储过程

    NULL 博文链接:https://xiaogui9317170.iteye.com/blog/286401

    oracle存储过程返回多行多列的结构化数组,java调用并解析

    java调用oracle输出参数为多行多列的结构化数组的存储过程,并将其遍历解析;该demo部署后,只需要配置poolman.xml数据源,即可运行;

    C#中调用oracle存储过程返回数据集

    C#中调用oracle存储过程返回数据集

    oracle数组存储过程批量插入

    今天做了一个关于短消息批量删除的功能, ... 所以就决定用 数组作为存储过程的参数进行传值,在存储过程中批量删除。说实话这个选择有点得不偿失,本来以为上午就能搞定,谁知道从摸索到实现,居然发了大半天时间。

    Mybatis传list参数调用oracle存储过程的解决方法

    怎么利用MyBatis传List类型参数到数据库存储过程中实现批量插入数据?接下来通过本文给大家介绍Mybatis传list参数调用oracle存储过程,需要的朋友可以参考下

    Java调用带参数的存储过程并返回集合

    Java调用带参数的Oracle 存储过程并返回集合,

    nls_charset12.jar oracle 10

    用java调用oracle存储过程,传入数组参数,数组项为空值。

    godror:用于 Oracle DB 的 GO 驱动程序

    甚至使用 OUT 参数调用存储过程,或发送/检索 PL/SQL 数组类型 - 只需在Exec的参数中提供一个godror.PlSQLArrays选项! 例如,返回的 PL/SQL 数组的数组大小可以通过godror.ArraySize(2000) (默认

    Dapper.Oracle:Oracle对Dapper Micro ORM的支持

    使用此程序包,您现在可以运行返回RefCursor的存储过程,或使用数组绑定计数来执行带有参数数组的sql语句。 受支持的Oracle特定属性 OracleParameter(托管和非托管) OracleDbType枚举(托管提供者使用的所有成员...

    不固定参数的存储过程实现代码

    我们知道存储过程是不支持不固定参数情况的(包括数组参数),可是有时候我们的参数又必须是不固定的,怎么办呢?

    Oracle8i_9i数据库基础

    §16.2.2 使用过程 278 §16.2.3 开发存储过程步骤 279 §16.2.3.1 编辑存储过程源码 279 §16.2.3.2 对存储过程程序进行解释 279 §16.2.3.3 调试源码直到正确 279 §16.2.3.4 授权执行权给相关的用户或角色 279 §...

    oracle学习文档 笔记 全面 深刻 详细 通俗易懂 doc word格式 清晰 连接字符串

    其一、就业面广:全球前100强企业99家都在使用ORACLE相关技术,中国政府机构,大中型企事业单位都能有ORACLE技术的工程师岗位。 其二、技术层次深:如果期望进入IT服务或者产品公司(类似毕博、DELL、IBM等),...

    Oracle 10g 开发与管理

    我相信本文会对初学者使用oracle有一个初步的使用印象。右图为我所参 考的书籍。 目录 第一讲 Oacle关系数据库 9 一. Oracle的安装 9 二. 用浏览器进入em 企业管理器 11 三.启动DBCA的方法 11 四.服务设置 11...

    oracle详解

    而GRANTS和INDEXES则表示是否导入授权和索引,如果想使用新的存储参数重建索引,或者为了加快到入速度,我们可以考虑将INDEXES设为N,而GRANTS一般都是Y。例如:imp userid=test1/test1 file=expdat.dmp fromuser=...

    疯狂JAVA讲义

    4.5.4 使用数组 90 学生提问:为什么要我记住这些异常信息? 91 4.5.5 JDK1.5提供了foreach循环 91 4.6 深入数组 93 4.6.1 内存中的数组 93 学生提问:为什么有栈内存和堆内存之分? 93 4.6.2 基本类型数组的...

    springmybatis

    MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis使用简单的XML或注解用于配置和原始映射,将接口和Java的POJOs(Plan ...

    JavaProgrammer1

    使用args数组中存储的参数,在控制台中显示一条消息。作业1.3 Java程序员的一项重要技能是能够读取和理解Java API。甲部简要回顾一下java.util包中的Arrays类(请注意,在Java Associate 8考试中无法检查Arrays类)...

    php网络开发完全手册

    16.3.3 存储过程的参数 265 16.3.4 复合语句 267 16.3.5 变量 268 16.3.6 条件语句 269 16.3.7 循环语句 271 16.3.8 游标 273 16.3.9 存储过程的删除 275 16.4 触发器的设计 275 16.4.1 触发器的创建与触发 275 ...

    数据库基础

    §16.2.2 使用过程 278 §16.2.3 开发存储过程步骤 279 §16.2.3.1 编辑存储过程源码 279 §16.2.3.2 对存储过程程序进行解释 279 §16.2.3.3 调试源码直到正确 279 §16.2.3.4 授权执行权给相关的用户或角色 279 §...

Global site tag (gtag.js) - Google Analytics