Java 在Oracle SQL中使用JDBC获取自定义类型的表作为输出参数

Java 在Oracle SQL中使用JDBC获取自定义类型的表作为输出参数,java,oracle,jdbc,plsql,ojdbc,Java,Oracle,Jdbc,Plsql,Ojdbc,我正在编写一个POC来测试从现有PLSQL函数中获取一个自定义类型的表作为输出参数,我的类型在包和模式级别都有定义,但我的函数使用包类型 我编写了一个java程序,它调用这个函数并假定获取输出参数,但在执行该语句时,我一直得到一个无效参数。我认为Java不接受包中定义的类型,这就是为什么该类型也在模式级别上定义的原因,注意到如果我更改了我的函数以使用模式类型,它可以正常工作,但我需要保留现有签名,因为它在其他地方使用。对于模式和包类型之间的链接,我发现我需要创建一个结构描述符,但是它似乎无法链接

我正在编写一个POC来测试从现有PLSQL函数中获取一个自定义类型的表作为输出参数,我的类型在包和模式级别都有定义,但我的函数使用包类型

我编写了一个java程序,它调用这个函数并假定获取输出参数,但在执行该语句时,我一直得到一个无效参数。我认为Java不接受包中定义的类型,这就是为什么该类型也在模式级别上定义的原因,注意到如果我更改了我的函数以使用模式类型,它可以正常工作,但我需要保留现有签名,因为它在其他地方使用。对于模式和包类型之间的链接,我发现我需要创建一个结构描述符,但是它似乎无法链接这两种类型。链接中是否缺少某些内容,或者这是无法实现的

下面是java程序:

public class Main {
    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        Connection connection = DriverManager.getConnection("connection url", "username", "password");

        final String typeName = "R_ERROR";
        final String typeTableName = "T_ERROR";

        final StructDescriptor structDescriptor = StructDescriptor.createDescriptor(typeName, connection);
        final ResultSetMetaData metaData = structDescriptor.getMetaData();

        OracleCallableStatement cstmt = (OracleCallableStatement) connection.prepareCall("begin ? := test_kc_fn(?); end;");
        cstmt.registerOutParameter(1, Types.VARCHAR);
        cstmt.registerOutParameter(2, Types.ARRAY, typeTableName);

        cstmt.execute();

//        Object[] data = (Object[]) ((Array) cstmt.getObject(2)).getArray();
//        for(Object tmp : data) {
//            Struct row = (Struct) tmp;
//            int index = 1;
//            for(Object attr : row.getAttributes()) {
//                if(index == 1) {
//                    System.out.print(metaData.getColumnName(index) + ": " + attr);
//                } else {
//                    System.out.print(metaData.getColumnName(index) + ": " + attr + " - ");
//                }
//
//                ++index;
//            }
//            System.out.println();
//        }

        System.out.println("Done!");
    }
}
以及PLSQL代码:

create type r_error as object (
  rowIden varchar2(36 char),
  severity varchar2(1),
  fld varchar2(30 char),
  text varchar2(1000 char)
);

create type t_Error as table of r_error;

create or replace package pkg_kc as 
  type r_error is record (
    rowIden varchar2(36 char),
    severity varchar2(1),
    fld varchar2(30 char),
    text varchar2(1000 char)
  );

  type t_error is table of r_error index by binary_integer;

  procedure add_error(o_errorlist in out t_error, i_text varchar2);
end pkg_kc;

create or replace package body pkg_kc as 

  procedure add_error(o_errorlist in out t_error, i_text varchar2) is
    v_rowId number;
    v_row r_error;
  begin
    if o_errorlist is not null then
      v_rowId := o_errorlist.count + 1;

      v_row.rowIden := v_rowId;
      v_row.severity := 'E';
      v_row.fld := null;
      v_row.text := i_text;

      o_errorlist(v_rowId) := v_row;
    end if;
  end;
end pkg_kc;

create or replace function test_kc_fn (o_errlist out pkg_kc.t_error) return varchar2 as
begin
  pkg_kc.add_error(o_errlist, 'message 1'); 
  pkg_kc.add_error(o_errlist, 'message 2');
  pkg_kc.add_error(o_errlist, 'message 3');
  return 'F';
end;

您应该只使用数据库级别类型而不是包级别类型声明您的过程使用的类型不是来自包您应该只使用数据库级别类型而不是包级别类型声明您的过程使用的类型不是来自包