2012-02-10 46 views
4

我非常接近解決這個問題,但我顯然缺少一些東西。我的要求是從JDBC調用Oracle中的存儲過程。存儲過程將1個用戶定義的Oracle對象作爲INput,另一個用戶定義的Oracle對象作爲OUTput。 INput和OUTput對象混合使用原始Oracle數據類型和另一組用戶定義對象的集合。只要我爲INput和OUTput對象中的集合類型設置NULL,我就可以成功調用存儲過程並返回結果。如果我嘗試爲Oracle對象列表創建ArrayDescriptor以將其發送到存儲過程,我不斷碰到障礙。所以我需要幫助解決如何將數組設置爲INput對象並將其設置爲CallableStatement。請注意,我知道如何將原始類型和數組作爲直接輸入發送到存儲過程。但我不想這樣做,因爲我們稍後必須向過程發送10個附加字段,我不想將它們添加到方法簽名中。這是類的列表。此外,下面的代碼沒有編譯錯誤。從複雜的輸入輸出類型JDBC調用Oracle存儲過程

包裝在Oracle:

CREATE OR REPLACE TYPE TESTDATA_IN_OBJ AS OBJECT(
testStr1   VARCHAR2(5), 
arrObj1    ARR_OBJ_1_NT); 

陣列對象作爲輸入對象的一部分::

create or replace TYPE  ARR_OBJ_1_NT AS TABLE OF ARR_OBJ_1_OBJ; 
存儲過程

CREATE OR REPLACE PACKAGE testPkg AS 
PROCEDURE spGetTestData (
TESTDATA_IN    IN   TESTDATA_IN_OBJ, 
TESTDATA_OUT  OUT    TESTDATA_OUT_OBJ 
); 
END; 

輸入對象

輸入對象的用戶自定義的對象部分:

CREATE OR REPLACE TYPE ARR_OBJ_1_OBJ AS OBJECT 
(
teststr   VARCHAR2(14), 
testNumber NUMBER(4), 
); 

TestDataINObj.java:

import java.sql.Array; 
    import java.sql.SQLData; 
    import java.sql.SQLException; 
    import java.sql.SQLInput; 
    import java.sql.SQLOutput; 

    public class TestDataINObj implements SQLData 
    { 
private String sql_type = "TESTDATA_IN_OBJ"; 

protected String testStr1; 
protected Array arrObj1; 

@Override 
public String getSQLTypeName() throws SQLException 
{ 
    return this.sql_type; 
} 


    // getter and setter for fields 

@Override 
public void readSQL(SQLInput stream, String typeName) throws SQLException 
{ 
this.sql_type=typeName; 
    this.testStr1 = stream.readString(); 
    this.arrObj1 = stream.readArray(); 
} 

@Override 
public void writeSQL(SQLOutput stream) throws SQLException 
{ 
    stream.writeString(this.testStr1); 
    stream.writeArray(this.arrObj1); 
} 
    } 

TestDataINObjConverter.java

public class TestDataINObjConverter 
    { 
    public static TestDataINObj convertPOJOToDBInObj(Connection connection) 
     throws SQLException 
    { 
    TestDataINObj testDataINObj = new TestDataINObj(); 
     testDataINObj.setTestStr1("some string"); 
     ArrObj1NT[] ArrObj1NTList = ArrObj1NTConverter.convertPOJOToDBObj(); // this will return Java array of ArrObj1NT class 
     testDataINObj.setArrObj1(getOracleArray("ARR_OBJ_1_NT",connection, ArrObj1NTList)); 
    return testDataINObj; 
} 


private static Array getOracleArray(final String typeName, Connection connection, ArrObj1NT[] ArrObj1NTList) throws SQLException 
{ 
    if (typeName == null) 
    { 
     return null; 
    } 
    Array oracleArray = new ARRAY(new ArrayDescriptor(typeName, connection), connection, ArrObj1NTList); 
    return oracleArray; 
} 

代碼實際執行調用存儲過程

... //code to get connection 
    ..// connection is of type T4CConnection 
    Map typeMap = connection.getTypeMap(); 
     typeMap.put("TESTDATA_IN_OBJ", TestDataINObj.class); 
     typeMap.put("TESTDATA_OUT_OBJ", TestDataOUTObj.class); 
     typeMap.put("ARR_OBJ_1_NT", ArrObj1NT.class); 

     TestDataINObj testDataINObj = TestDataINObjConverter.convertPOJOToDBInObj(connection); 

     getMetaDataCallableStatement = connection.prepareCall("begin " + "testPkg" + ".spGetTestData (?,?);"+ " end;"); 
     getMetaDataCallableStatement.setObject(1, testDataINObj); 
     getMetaDataCallableStatement.registerOutParameter(2, Types.STRUCT, "TESTDATA_OUT_OBJ"); 
     rs = getMetaDataCallableStatement.executeQuery(); 

     TestDataOUTObj testDataOUTObj = (TestDataOUTObj) getMetaDataCallableStatement.getObject(2, typeMap); 

其他: 1.對象是在模式級聲明,可用於數據庫用戶訪問它。 2.我沒有在這裏包含所有相應的Java對象,因爲它需要更多的空間。他們實現SQLData接口,他們的類型名稱與數據庫名稱匹配。 read和writeSQL方法使用getString,getArray和相應的setter方法。

+0

你正走向正確的道路。你能發佈你得到的例外嗎? – Nick 2012-05-29 17:50:31

+0

TESTDATA_OUT_OBJ聲明在哪裏? – Nagh 2012-08-13 01:22:34

+0

嘿,你有答案嗎? – 2017-02-22 11:09:17

回答

0

這是一個非常古老的方法,爲什麼你不使用「Oradata」和「Oradatum」界面? 這將節省很多努力。

你的方法留下了很多scopr的錯誤,你將不得不以適當的方式閱讀流,並檢查自己的領域排序可能會非常棘手。 Oradata方法將爲你做到這一點。

即將到來的方法,您的代碼不是很清楚。 但是,只是爲了給出一個概述,StructDescriptor將映射到oracle記錄類型,並且ArrayDescriptor將映射到oracle表類型,從您的代碼中我很困惑你正試圖實現的。

我可以幫助,如果你可以更清楚。

相關問題