【问题标题】:plsql - how to return associative array to javaplsql - 如何将关联数组返回给java
【发布时间】:2016-10-12 13:46:29
【问题描述】:

我正在尝试将关联数组返回给 java,但遇到异常。我正在使用专有的持久层,所以我无法发布我的代码,但是在谷歌上搜索时,我发现了一些与我所拥有的完全相似的东西:

============================

create or replace PACKAGE testLookAside as
type AssocArry IS TABLE OF varchar(30) INDEX BY VARCHAR(30);
function lookupMasterData return AssocArry;
end testLookAside;
/
create or replace PACKAGE BODY testLookAside as
function lookupMasterData_ return AssocArry as
retval AssocArry;
begin
retval('1') := '1';
retval('2') := '2';
retval('3') := '3';
retval('4') := '4';
return retval;
end lookupMasterData_;
/
function lookupMasterData return AssocArry as
retVal AssocArry;
begin
retVal := lookupMasterData_();
return retVal;
end lookupMasterData;
end testLookAside;

Statement s = null;;
Class.forName("oracle.jdbc.driver.OracleDriver");
// set up connection here....
s=con.createStatement();

//String query = "begin ? := DEVELOPER.testLookAside.lookupMasterData(); end;";
String query = "{? = call DEVELOPER.testLookAside.lookupMasterData()}";

OracleCallableStatement stmt = (OracleCallableStatement)con.prepareCall(query);

// register the type of the out param - an Oracle specific type
stmt.registerIndexTableOutParameter(1, 30, OracleTypes.VARCHAR, 30);

stmt.execute();

而且我不断收到如下错误:

Exception in thread "main" java.sql.SQLException: ORA-06550: line 1, column 13:
PLS-00382: expression is of wrong type
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

谁能解释从 jdbc 访问该数据类型的正确方法是什么?

另外,如果我的自定义类型像这样使用数字和二进制整数,我该怎么办:

type AssocArry IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;

我从上周开始尝试解决这个问题,并查看了许多线程但没有结果。

谢谢。

【问题讨论】:

  • 您使用的是哪个版本的 Oracle 数据库和 Oracle JDBC 驱动程序? Oracle 12c JDBC Developer guide 这里有一个关于关联数组的章节:docs.oracle.com/database/121/JJDBC/oraint.htm#JJDBC28179 但 Oracle 11.2 文档没有在任何地方提到它们,可能是旧版本的数据库和驱动程序根本不支持它们。

标签: java oracle jdbc plsql associative-array


【解决方案1】:

我想说的是,没有直接的方法可以从 JDBC 访问声明为 TABLE OF varchar(30) INDEX BY VARCHAR(30) 的数据类型。

Oracle JDBC documentation 在各个地方都提到了关联数组的元素类型(即您的类型中的第一个varchar(30)),但据我所知,它没有说明关键数据类型。此外,文档提到关联数组作为 Java 数组传入和返回。这让我怀疑 Oracle JDBC 只支持以 BINARY_INTEGER 作为键数据类型的关联数组。

因此,如果您想通过 JDBC 使用 VARCHAR2 键访问 PL/SQL 关联数组中的数据,我建议您先将数据转换为另一种数据类型。

但是,我希望您编写的 JDBC 代码将使用 BINARY_INTEGER 键处理您的关联数组,一旦您在对 registerIndexTableOutParameter 的调用中将 OracleTypes.VARCHAR 更改为 OracleTypes.NUMERIC。请注意,返回的 Java 数组将包含与最大键值一样多的元素,因此请确保最大元素数(registerIndexTableOutParameter 的第二个参数)足够大。还要确保关联数组没有负键或零键,因为 JDBC 驱动程序似乎也不支持这些。


作为参考,这是我用来获取声明为 INDEX BY BINARY_INTEGER 的关联数组的代码。首先,PL/SQL 包和主体:

create or replace PACKAGE testLookAside as
  type AssocArry IS TABLE OF number INDEX BY binary_integer;
  function lookupMasterData return AssocArry;
end testLookAside;
/

create or replace PACKAGE BODY testLookAside as
  function lookupMasterData return AssocArry as
    retval AssocArry;
  begin
    retval(2) := 1;
    retval(4) := 2;
    retval(7) := 3;
    retval(1) := 4;
    return retval;
  end lookupMasterData;
end testLookAside;
/

其次,Java类:

import java.math.BigDecimal;
import java.sql.*;
import java.util.Arrays;
import oracle.jdbc.OracleCallableStatement;
import oracle.jdbc.OracleTypes;

public class AssocArrayTest {
    public static void main(String[] args) throws Exception {
        Connection c = DriverManager.getConnection("url", "user", "password");
        OracleCallableStatement s = (OracleCallableStatement)c.prepareCall("{? = call testLookAside.lookupMasterData }");
        s.registerIndexTableOutParameter(1, 30, OracleTypes.NUMERIC, 0);
        s.execute();
        BigDecimal[] data = (BigDecimal[])s.getPlsqlIndexTable(1);
        System.out.println(Arrays.toString(data));
    }
}

当我运行 Java 类时,我得到以下输出:

[4, 1, null, 2, null, null, 3]

【讨论】:

  • 感谢您的回复卢克。根据您的建议,我将代码更改为使用 BINARY_INTEGER。 TYPE NUMBER_ARRAY_TYPE IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;。还像这样getOracleStatement(cstmt).registerIndexTableOutParameter(bindOffset, m_maxLen, OracleTypes.NUMERIC, m_elemMaxLen); 更改了 registerIndexTableOutParameter。我仍然看到同样的异常:-(
  • @boxfish:如果它有助于我添加到我用来检索 PL/SQL 关联数组的答案示例代码中,BINARY_INTEGER 作为关键数据类型。
猜你喜欢
  • 1970-01-01
  • 2013-08-16
  • 2013-03-08
  • 2011-04-27
  • 1970-01-01
  • 1970-01-01
  • 2011-10-24
  • 2017-01-24
  • 1970-01-01
相关资源
最近更新 更多