我一直在开发对存储过程的 Java/JDBC 调用,并取得了一些成功。但是,当输出参数是一个字符串数组时,我被卡住了。我成功地将标量类型用作输入和输出参数,并将字符串数组用作输入参数。
这是我的 PL/SQL 代码:
TYPE StringArray IS TABLE OF VARCHAR2(32767) INDEX BY BINARY_INTEGER;
create or replace package body
test is
procedure upper(
in_array in StringArray,
out_array out StringArray
) is
tmp StringArray := in_array;
begin
for i in 0..(tmp.count-1) loop
tmp(i) := UPPER(tmp(i));
end loop;
out_array := tmp;
end;
end test;
这是我的 Java 代码:
public void testString(Connection connection) {
String[] values = { "alpha", "beta", "gamma" };
try {
CallableStatement callableStatement = connection.prepareCall("begin test.upper(?, ?); end;");
DelegatingConnection<OracleConnection> delegatingConnection = (DelegatingConnection<OracleConnection>) new DelegatingConnection(connection);
OracleConnection oracleConnection = (OracleConnection) delegatingConnection.getInnermostDelegate();
Array input oracleConnection.createOracleArray("STRINGARRAY", values);
callableStatement.setObject("in_array", input);
callableStatement.registerOutParameter("out_array", Types.ARRAY, "STRINGARRAY");
callableStatement.execute();
Array output = (Array)callableStatement.getObject("out_array");
String[] result = (String[])output.getArray();
System.out.println("Length: " + result.length); // Prints "Length: 3"
System.out.println("First: " + result[0]); // Prints "First: null"
} (catch SQLException e) {
// Handle error
}
}
如果我直接从 SQL 脚本调用 PL/SQL 存储过程,它就可以工作。所以我觉得存储过程本身是可以的。
如果我通过 JDBC 调用存储过程,它会正常完成。使用调试语句,我已确认 values
已从 Java 客户端正确发送到存储过程到 in_array
中。也就是说,接收到具有适当值的长度为 3 的数组。据我所知,out_array
被发送回 Java 客户端。但是,出了点问题。 result
的大小为 3,但所有元素都是 null
。
如果我检查 output
,我可以看到它内部有一个长度为 38 的 byte[]
。这些字节的子序列映射到“ALPHA”,“BETA”和“GAMMA”。因此,看起来数据已返回客户端,但未正确转换为 String[]
。
我做错了什么?
最佳答案
不要使用关联数组 - 使用集合:
CREATE TYPE StringArray IS TABLE OF VARCHAR2(4000);
CREATE TYPE CLOBArray IS TABLE OF CLOB;
然后你可以这样做:
public void testString(Connection connection) {
String[] values = { "alpha", "beta", "gamma" };
try {
OracleConnection oc = (OracleConnection) connection;
ARRAY stringArray = oc.createARRAY( "STRINGARRAY", values ); // Upper case identifier
OracleCallableStatement st = (OracleCallableStatement) oc.prepareCall(
"begin test.upper( :in_array, :out_array ); end;"
);
st.setARRAYAtName( "in_array", stringArray );
st.registerOutParameter( "out_array", Types.ARRAY, "STRINGARRAY"); // Upper case again
st.execute();
String[] result = (String[])st.getARRAY( 2 ).getArray();
System.out.println("Length: " + result.length);
System.out.println("First: " + result[0]);
} (catch SQLException e) {
// Handle error
}
}
如果您必须使用 PL/SQL 关联数组作为过程的输入,那么编写一个函数,它接受一个集合并输出一个适当类型的关联数组,然后调用它:
BEGIN TEST.UPPER( TO_ASSOC_ARRAY( :in_collection ), :out_array ); END;
注意:此答案假设在 ojdbc6.jar 中使用 Oracle 驱动程序似乎没有 OracleConnection.createOracleArray()
method但希望它可以移植,将 oracle.sql.ARRAY
更改为 java.sql.Array
并使用更新的方法。
关于java - 如何获得作为数组工作的存储过程输出参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47707903/