java oracle传入和取得自定义数组(二维数组)

环境

oracle数据库为11g

oracle数据库准备

--创建测试表
drop table t_parent;
drop table t_child;
create table t_parent(
    id number(10),
    name varchar2(100),
    title varchar2(100)
);

create table t_child(
    id number(10),
    parent_id number(10),
    child_name varchar2(100),
    child_title varchar2(100)
);
--创建测试序列
create sequence seq_test
minvalue 1
maxvalue 9999999999
start with 1
increment by 1
nocache;
--创建oracle数组类型
drop type t_child_lst_map;
drop type t_child_lst;
drop type t_parent_lst;

create or replace type t_parent_ as object (
    name varchar2(100),
    title varchar2(100)
);
create or replace type t_child_ as object (
    child_name varchar2(100),
    child_title varchar2(100)
);
create or replace type t_parent_lst as table of t_parent_;
create or replace type t_child_lst as table of t_child_;
create or replace type t_child_lst_map as table of t_child_lst;

--存储过程
--包头
create or replace package p_arraylist_test is
  --输入输出自定义数组参数的存储过程
  procedure proc_lst_test(i_parent_lst    in t_parent_lst, --parent列表
                          i_child_map_lst in t_child_lst_map, --child列表集合,一个map元素对应一个child_lst,其下标与 parent列表的下标相同。
                          o_oarent_list   out t_parent_lst, --parent列表
                          o_ret           out number);
end p_arraylist_test;
--包体
create or replace package body p_arraylist_test is

  --输入输出自定义数组参数的存储过程
  procedure proc_lst_test(i_parent_lst    in t_parent_lst, --parent列表
                          i_child_map_lst in t_child_lst_map, --child列表集合,一个map元素对应一个child_lst,其下标与 parent列表的下标相同。
                          o_oarent_list   out t_parent_lst, --parent列表
                          o_ret           out number) as
    var_parent    t_parent_;
    var_child_lst t_child_lst;
    var_child     t_child_;
    var_parent_id number;
  begin
    for i in 1 .. i_parent_lst.count loop
      --取得parent各列的值
      var_parent := i_parent_lst(i);

      --插入parent表
      insert into t_parent
        (id, name, title)
      values
        (seq_test.nextval, var_parent.name, var_parent.title) return id into var_parent_id;

      --取得该parent对应的child列表
      var_child_lst := i_child_map_lst(i);

      for j in 1 .. var_child_lst.count loop
        var_child := var_child_lst(j);

        --插入child表
        insert into t_child
          (id, parent_id, child_name, child_title)
        values
          (seq_test.nextval,
           var_parent_id,
           var_child.child_name,
           var_child.child_title);
      end loop;

    end loop;
    -- 给数组赋值
    o_oarent_list := t_parent_lst();
    for idx in (select * from t_parent where rownum < 5) loop
      o_oarent_list.extend; -- 扩展数组,以便于给数组赋值
      -- 赋值的时候,下标必须从 1 开始,否则会出现 “ 下标超出数量 ” 的错误
      o_oarent_list(o_oarent_list.count) := t_parent_(idx.name, idx.title);
    end loop;

    o_ret := 1;

  exception
    when others then
      begin
        o_ret := 0;
        raise;
      end;
  end proc_lst_test;

end p_arraylist_test;

--常见问题:
/*
1.存入的值为空,但是记录有插入,插入值为空
解决:查看当前lib包中有没有包含orai18n.jar库.
*/

--清除痕迹
drop table t_parent;
drop table t_child;

drop type t_child_lst_map;
drop type t_child_lst;
drop type t_parent_lst;
drop type t_parent_;
drop type t_child_;

drop sequence seq_test;
drop package p_arraylist_test;

java代码

package com.lytz.work;

import java.sql.Connection;
import java.sql.DriverManager;

/**
 * TestCon.java 说明
 * 
 * @author zhengzy
 * @date 2015年12月8日下午3:31:57
 */
public class TestCon {
    public static Connection getConn() {
        String URL = "jdbc:oracle:thin:@192.168.15.45:1521:lytzats";
        String user = "atsol";// 这里替换成你自已的数据库用户名
        String password = "atsol";// 这里替换成你自已的数据库用户密码
        Connection connection = null;
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver");
            System.out.println("类实例化成功!");
            connection = DriverManager.getConnection(URL, user, password);
            System.out.println("创建连接对像成功!");
        } catch (Exception err) {
            err.printStackTrace();
            return null;
        }
        return connection;
    }

    public static void main(String[] args) {
        getConn();
    }
}
package com.lytz.work;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;

import oracle.jdbc.OracleTypes;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;
import oracle.sql.Datum;
import oracle.sql.STRUCT;
import oracle.sql.StructDescriptor;

import com.lytz.db.manager.DBUtil;

/**
 * Test.java 说明
 * 
 * @author zhengzy
 * @date 2015年12月4日下午2:20:28
 */
public class Test {

    public static void main(String[] args) throws InterruptedException, SQLException {

        Connection con = null;
        CallableStatement  cstmt = null;

//      con = DBUtil.getInstance().getConnection();
        con = TestCon.getConn();

        ArrayList<Parent> plst = new ArrayList<Parent>();
        for (int i = 0; i < 10; i++) {
            Parent p = new Parent();
            p.setName("name" + i);
            p.setTitle("title" + i);
            plst.add(p);
        }

        ArrayList<ArrayList<Child>> clstMap = new ArrayList<ArrayList<Child>>();
        for (int i = 0; i < 10; i++) {
            ArrayList<Child> clst = new ArrayList<Child>();
            for (int j = 0; j < 10; j++) {
                Child c = new Child();
                c.setChild_name("childName" + j);
                c.setChild_title("childT" + j);
                clst.add(c);
            }
            clstMap.add(clst);
        }

        //此处的参数必须为大写
        ArrayDescriptor parentLstDesc = ArrayDescriptor.createDescriptor("T_PARENT_LST", con);
        StructDescriptor parentDesc = StructDescriptor.createDescriptor("T_PARENT_", con);
        ArrayDescriptor childLstMapDesc = ArrayDescriptor.createDescriptor("T_CHILD_LST_MAP", con);
        ArrayDescriptor childLstDesc = ArrayDescriptor.createDescriptor("T_CHILD_LST", con);
        StructDescriptor childDesc = StructDescriptor.createDescriptor("T_CHILD_", con);

        ArrayList<STRUCT> pstruct = new ArrayList<STRUCT>();
        // 转换plst为Oracle 对象数组
        for (int i = 0; i < plst.size(); i++) {
            Parent p = plst.get(i);
            Object[] record = new Object[2];
            record[0] = p.getName();
            record[1] = p.getTitle();
            STRUCT item = new STRUCT(parentDesc, con, record);
            pstruct.add(item);
        }
        ARRAY dataps = new ARRAY(parentLstDesc, con, pstruct.toArray());

        ArrayList<ARRAY> cMap = new ArrayList<ARRAY>();
        // 转换clst为Oracle 对象数组
        for (int i = 0; i < clstMap.size(); i++) {
            ArrayList<Child> childLst = clstMap.get(i);
            ArrayList<STRUCT> cstruct = new ArrayList<STRUCT>();
            for (int j = 0; j < childLst.size(); j++) {
                Child c = childLst.get(j);
                Object[] record = new Object[2];
                record[0] = c.getChild_name();
                record[1] = c.getChild_title();
                STRUCT item = new STRUCT(childDesc, con, record);
                cstruct.add(item);
            }
            ARRAY datacs = new ARRAY(childLstDesc, con, cstruct.toArray());
            cMap.add(datacs);
        }
        ARRAY datacsMap = new ARRAY(childLstMapDesc, con, cMap.toArray());

        try {
            cstmt = con.prepareCall("{call P_ARRAYLIST_TEST.PROC_LST_TEST(?,?,?,?)}");

            cstmt.setArray(1, dataps);
            cstmt.setArray(2, datacsMap);
            cstmt.registerOutParameter(3, OracleTypes.ARRAY, "T_PARENT_LST");
            cstmt.registerOutParameter(4, OracleTypes.INTEGER);
            cstmt.execute();

            int error_code = cstmt.getInt(4);
            System.out.println(error_code);

            ARRAY ary = (ARRAY) cstmt.getArray(3);
            Datum[] dtm = ary.getOracleArray();
            for (int i = 0; i < dtm.length; i++) {
                STRUCT st = (STRUCT) dtm[i];
                Object obj[] = st.getAttributes();
                System.out.println(obj[0] + "---" + obj[1]);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (cstmt != null) {
                    cstmt.close();
                    cstmt = null;
                }
                if (con != null) {
                    con.close();
                    con = null;
                }
            } catch (SQLException ex) {
                logger.error("数据库资源释放出错:" + ex.getMessage());
                // ex.printStackTrace();
            }
        }
    }
}

结果

这里写图片描述

问题

问题:
java.sql.SQLException: ORA-06530: 引用未初始化的组合

原因:
数组初始化方式有问题

  procedure proc_lst_test_out2(o_oarent_ out t_parent_ --parent列表
                               ) as
  begin

    --o_oarent_ := t_parent_('test', 'title');
    o_oarent_.name := 'test';
    o_oarent_.title := 'title';

  end proc_lst_test_out2;

以上代码是不行的

解决:

  procedure proc_lst_test_out2(o_oarent_ out t_parent_ --parent列表
                               ) as
  begin

    o_oarent_ := t_parent_('test', 'title');

  end proc_lst_test_out2;

参考

Java中传入和取得oracle10g存储过程返回的数组对象(多维数组)http://blog.csdn.net/hunterdiary/article/details/6063279

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值