2012-12-10 66 views
2

我想將一個oracle過程調用的out參數強制轉換爲對象。它不起作用,因爲 - 據我瞭解 - 我需要定義一個地圖,它告訴方法如何投射它。如果地圖是空格或不正確填充,它默認爲STRUCT類型的對象 - 這在我的情況中是錯誤的。如何在oracle中獲取一個表作爲輸出參數

我建一個樣品,這應該說明問題:由於錯誤地圖的

-- Procedure in database 
PROCEDURE myprocedure (
inputParam    IN  VARCHAR2 (4), 
outputOne     OUT outputOneSQLType 
outputTwo     OUT outputTwoSQLType); 

-- inside of a package 
inside a package mypackage 

-- first type 
create or replace 
TYPE outputOneSQLType IS TABLE OF tableOneExample 

-- table of type 
create or replace 
TYPE tableOneExample AS OBJECT (
     somethingOne     VARCHAR2 (4) 
    ,somethingTwo  NUMBER (12) 
) 

//java from here 

import oracle.jdbc.OracleCallableStatement; 
import oracle.jdbc.OracleTypes; 
import oracle.jdbc.oracore.OracleTypeADT; 
import oracle.sql.STRUCT; 
... 
oracle.jdbc.driver.OracleConnection oracleConn = (oracle.jdbc.driver.OracleConnection) con.getMetaData().getConnection(); 
final OracleCallableStatement storedProc = (OracleCallableStatement)oracleConn.prepareCall("{call mypackage.myprocedure("+ 
       ":inputParam, :outputOne, :outputTwo)}"); 

storedProc.setString("inputParam", "SomeValue"); 

storedProc.registerOutParameter("outputOne", OracleTypes.STRUCT, "OUTPUTONESQLTYPE"); 
storedProc.registerOutParameter("outputTwo", OracleTypes.STRUCT, "OUTPUTTWOSQLTYPE"); 

storedProc.execute(); 

//So far so good 

//now I am lost - I need to define the map to get the object? 
//What should be inside the map? 
Hashtable newMap = new Hashtable(); 

newMap.put("outputOneSQLType", ?????.class); 

//If the map is empty, it defaults to STRUCT... 
final STRUCT myObject = (STRUCT)storedProc.getObject("somethingOne",newMap); 
// myObject.getBytes() gives me an object... but I cannot cast it to anything 

,我不能使用成才,如:

final MyClass myObject = (MyClass)storedProc.getObject("somethingOne",newMap); 

我應如何填寫地圖?

編輯1

在Oracle數據庫中的條目不能被改變。我只被允許使用它們。因此,

stmt.registerOutParameter(2, java.sql.Types.ARRAY, "OUTPUTONESQLTYPE"); 

不起作用。因爲一旦我不使用「OracleTypes.STRUCT」就會引發異常。這似乎outputOneSQLType的這裏面有類型的對象「OracleTypeCOLLECTION」

當我嘗試

Hashtable newMap = new Hashtable(); 
newMap.put("outputOneSQLType",OracleTypeCOLLECTION.class); 
final OracleTypeCOLLECTION myObject = (OracleTypeCOLLECTION)storedProc.getObject("somethingOne",newMap); 

我得到一個異常:InstantiationException: oracle.jdbc.oracore.OracleTypeCOLLECTION

@DazzaL:我會嘗試定義一個接口SQLDATA 。也許這將是解決

SOLUTION

  1. 預處理語句應該是像 「開始package.procedure的(...);結束;」和「{呼叫package.procedure的(...)})需要
  2. 一個SQLDATA接口

@DazzaL:!你統治THX

回答

5

你必須定義一個SQLDATA對象映射此

文件:http://docs.oracle.com/cd/E11882_01/java.112/e16548/oraarr.htm#JJDBC28574

例如:

SQL> create or replace TYPE tableOneExample AS OBJECT (
    2  somethingOne     VARCHAR2 (4) 
    3  ,somethingTwo  NUMBER (12) 
    4 ); 
    5/

Type created. 

SQL> create or replace TYPE outputOneSQLType IS TABLE OF tableOneExample; 
    2/

Type created. 

SQL> 
SQL> create or replace PROCEDURE myprocedure (
    2 inputParam    IN  VARCHAR2, 
    3 outputOne     OUT outputOneSQLType) 
    4 as 
    5 begin 
    6 outputOne := outputOneSQLType(tableOneExample('a', 1), tableOneExample('b', 2)); 
    7 end; 
    8/

Procedure created. 

現在我們我們定義SQLData接口:

import java.sql.*; 

public class TestArr implements SQLData 
{ 
    private String sql_type; 

    public String attrOne; 
    public int attrTwo; 

    public TestArr() 
    { 
    } 
    public TestArr (String sql_type, String attrOne, int attrTwo) 
    { 
    this.sql_type = sql_type; 
    this.attrOne = attrOne; 
    this.attrTwo = attrTwo; 
    } 

    // define a get method to return the SQL type of the object 
    public String getSQLTypeName() throws SQLException 
    { 
    return sql_type; 
    } 

    // define the required readSQL() method 
    public void readSQL(SQLInput stream, String typeName) 
    throws SQLException 
    { 
    sql_type = typeName; 

    attrOne = stream.readString(); 
    attrTwo = stream.readInt(); 
    } 
    // define the required writeSQL() method 
    public void writeSQL(SQLOutput stream) 
    throws SQLException 
    { 
    stream.writeString(attrOne); 
    stream.writeInt(attrTwo); 
    } 
} 

確保輸入流的順序寫入/讀取是一樣的你的Oracle類型,因爲任何不一致會給內部表示錯誤。

CallableStatement stmt = conn.prepareCall("begin myprocedure(?,?); end;"); 
stmt.setString(1, "foo"); 
stmt.registerOutParameter(2, java.sql.Types.ARRAY, "OUTPUTONESQLTYPE"); // YOUR ARRAY TYPE (TO MATCH THE API OUTPUT), NOT OBJECT 
stmt.execute(); 
Array arr = stmt.getArray (2); 
Map map = conn.getTypeMap(); 
map.put("TABLEONEEXAMPLE", Class.forName("TestArr")); // YOUR OBJECT TYPE, NOT ARRAY. 
Object[] values = (Object[]) arr.getArray(); 
for (int i=0; i < values.length; i++) 
{ 
    TestArr a = (TestArr)values[i]; 
    System.out.println("somethingOne: " + a.attrOne); 
    System.out.println("somethingTwo: " + a.attrTwo); 
} 

結果bieng:

M:\Documents\Sample Code\1>javac TestArr.java 

M:\Documents\Sample Code\1>javac ArrayTest.java 
Note: ArrayTest.java uses unchecked or unsafe operations. 
Note: Recompile with -Xlint:unchecked for details. 

M:\Documents\Sample Code\SQLComplexArray>java ArrayTest 
Opening Oracle connection...done. 
somethingOne: a 
somethingTwo: 1 
somethingOne: b 
somethingTwo: 2 
+0

THX

然後在主類,你會如下映射此。我將嘗試定義一個SQLDATA接口。也許這將是解決方案。 –

+0

棒極了,謝謝!我希望我可以添加+10 – spiderman

+0

很好的爲我工作,發佈我的帖子 - http://stackoverflow.com/questions/25253448/java-plsql-call-table-of-records-from-java/25274486#25274486 – spiderman

相關問題