我正在编写一个 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;