2016-06-11 31 views
1

我想将关联数组返回给java,但面临异常。我使用专有的持久层,因此我将无法发布我的代码,但在谷歌上搜索时,我发现了与我的东西完全相似的东西:plsql - 如何将关联数组返回给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; 

我试图解决从最近1周这个问题,看着没有结果多个线程。

谢谢。

+0

哪您使用的是Oracle数据库和Oracle JDBC驱动程序的版本?有关'Oracle 12c JDBC开发人员指南'中关联数组的章节:https://docs.oracle.com/database/121/JJDBC/oraint.htm#JJDBC28179但Oracle 11。2文档没有在任何地方提及它们,可能是数据库的旧版本和驱动程序根本不支持它们。 – krokodilko

回答

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.VARCHAROracleTypes.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] 
+0

感谢您的回复卢克。按照您的建议,我将代码更改为使用BINARY_INTEGER。 'TYPE NUMBER_ARRAY_TYPE是NUMBER INDEX BY TABLE BY BINARY_INTEGER;'。像这样'getOracleStatement(cstmt).registerIndexTableOutParameter(bindOffset,m_maxLen,OracleTypes.NUMERIC,m_elemMaxLen);'也改变了registerIndexTableOutParameter。我仍然看到同样的例外:-( – boxfish

+0

@boxfish:万一它帮助我添加了我的答案示例代码,我用'BINARY_INTEGER'作为关键数据类型检索PL/SQL关联数组。 –