簡體   English   中英

JDBC:Oracle存儲過程返回嵌套表

[英]JDBC: Oracle stored procedure returns nested table

我在oracle(12c)中有一個存儲過程:

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教程的教程 (如果鏈接丟失,google為“使用Oracle Collections”)。 到目前為止,本教程對我沒有任何作用。

這是我在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 []的Datum []數組,但是普通的sql方法什么也沒給我。 例如,來自數組的getResultSet返回一個ResultSet,其中next始終返回true,但沒有元數據和實際數據。 getArray()返回numElements = -1等的數組。

我嘗試使用typeMap而沒有運氣:

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);

請幫忙和建議。 提前致謝。

我擔心我正在努力重現你所看到的行為。 我試圖整理一些可以重現你的問題的代碼,但它確實有效。 代碼如下,我希望它對你有用。

我使用了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>]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM