2016-01-12 72 views
3

我在Oracle有一个存储过程(12C):JDBC:Oracle存储过程返回嵌套表

PROCEDURE work(a OUT VARCHAR2, b OUT SYS_REFCURSOR) 

当我调用光标的结果包含的行的程序,所述行包括一些原始值的+一自定义类型:

CREATE TYPE ELEM AS OBJECT(ElemID INTEGER)) 
CREATE TYPE LIST AS TABLE OF ELEM 

所以,结果是一样的东西:

vcursor: 
------------------ 
COL1 COL2 LIST 
------------------ 
A B LIST([ELEM],[ELEM]) 
C D LIST([ELEM],[ELEM],[ELEM]) 
E F LIST([ELEM]) 

有一个教程收集Oracle tutorial(如果链接丢失,google为“使用Oracle集合”)。到目前为止,本教程还没有为我工作。

以下是我在java做:

Connection conn = ... 
CallableStatement statement = conn.prepareCall("{call work()}"); 
statement.registerOutParameter(1, OracleTypes.VARCHAR); 
statement.registerOutParameter(2, OracleTypes.CURSOR); 
statement.execute(); 

ResultSet rs = statement.getResultSet(2); 
// here should be the code which retrieves the nested table elements 
rs.next() 
Array list = rs.getArray(3); //oracle.sql.ARRAY 
Object[] elems = (Object[]) list.getArray(); // doesn't work 
// I also tried list.getResultSet() 

在调试我也看到,如果我投来oracle.sql.ARRAY并调用getOracleArray(),然后我看到了正确的大小和基准[]数组与Struct [],然而普通的sql方法没有给我什么。例如,数组中的getResultSet返回一个ResultSet,其中下一个总是返回true,但不包含元数据和实际数据。的getArray()返回数组包含numElements = -1等。

我试着用类型映射玩,没有运气:

Map map = conn.getTypeMap(); 
map.put("ELEM", Elem.class); 
//map.put("SCHEMA.ELEM", Elem.class); 
//map.put("LIST", Elem.class); 
//map.put("SCHEMA.LIST", Elem.class); 
conn.setTypeMap(map); 

请帮助和建议。提前致谢。

回答

1

恐怕我努力重现你所看到的行为。我试图把一些能够重现你的问题的代码放在一起,但它工作。代码如下,我希望对你有用。

我使用了ELEM类型的类型映射条目,但不是LIST。我也无法在CallableStatement接口上找到getResultSet(int)方法,因此我使用了getObject(int),并将其转换为ResultSet

万一它很重要,我在Windows 10 x64上使用Oracle 11g XE 11.2.0.2.0,Java 1.8.0_60,ojdbc7.jar 12.1.0.2.0版本。我也尝试了ojdbc6.jar和ojdbc5.jar的版本,并且他们有相同的结果。

SQL:

CREATE TYPE elem AS OBJECT(ElemID INTEGER); 
/

CREATE TYPE list AS TABLE OF elem; 
/

CREATE OR REPLACE PROCEDURE work(a OUT VARCHAR2, b OUT SYS_REFCURSOR) 
AS 
BEGIN 
    a := 'test 1234'; 
    OPEN b FOR 
    SELECT 'A' AS col1, 'B' AS col2, list(elem(14), elem(17)) FROM DUAL 
    UNION ALL 
    SELECT 'C' AS col1, 'D' AS col2, list(elem(8), elem(4), elem(11)) FROM DUAL 
    UNION ALL 
    SELECT 'E' AS col1, 'F' AS col2, list(elem(-1)) FROM DUAL; 
END work; 
/

Elem.java:

import java.sql.*; 

public class Elem implements SQLData { 

    private Integer elementId; 

    public String getSQLTypeName() { return "ELEM"; } 

    public void readSQL(SQLInput input, String typeName) throws SQLException { 
     elementId = input.readInt(); 
    } 

    public void writeSQL(SQLOutput output) { 
     throw new UnsupportedOperationException(); 
    } 

    public String toString() { 
     return "<Element " + elementId + ">"; 
    } 
} 

JDBCStructs.java:

import java.sql.*; 
import java.util.*; 

public class JDBCStructs { 
    public static void main(String[] args) throws Exception { 
     Connection c = ... 

     Map<String, Class<?>> map = c.getTypeMap(); 
     map.put("ELEM", Elem.class); 
     c.setTypeMap(map);   

     CallableStatement cs = c.prepareCall("{call work(?, ?)}"); 
     cs.registerOutParameter(1, Types.VARCHAR); 
     cs.registerOutParameter(2, oracle.jdbc.OracleTypes.CURSOR); 
     cs.execute(); 
     String a = cs.getString(1); 
     System.out.println("Got string " + a); 
     ResultSet rSet = (ResultSet)cs.getObject(2); 
     while (rSet.next()) { 
      String col1 = rSet.getString(1); 
      String col2 = rSet.getString(2); 
      Array list = (Array)rSet.getObject(3); 
      System.out.println("Got " + col1 + ", " + col2 + " and " + Arrays.toString((Object[])list.getArray())); 
     } 
    } 
} 

输出:

Got string test 1234 
Got A, B and [<Element 14>, <Element 17>] 
Got C, D and [<Element 8>, <Element 4>, <Element 11>] 
Got E, F and [<Element -1>] 
+0

我用ojdbc6- 6.0。我很惊讶,它为你工作..不幸的是,它决定将嵌套表更改为包含对象的xml字符串,所以我们可以将它解析回单独的元素。如果我再次遇到同样的问题,我接受答案并尝试验证代码。非常感谢! –