2016-06-11 104 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關聯數組。 –