2012-12-10 2 views
2

오라클 프로 시저 호출의 out 매개 변수를 객체로 전송하려고합니다. 내가 이해할 수 있듯이, 메소드를 캐스팅하는 방법을 알려주는 맵을 정의해야하기 때문에 작동하지 않습니다. 지도가 emtpy이거나 정확하지 않은 경우, 기본적으로 STRUCT 유형의 객체로 설정됩니다. 이는 제 경우에는 잘못된 것입니다.오라클에서 out 매개 변수로 테이블을 가져 오는 방법

내가 문제를 설명한다 샘플 구축이 :

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

은 어떻게지도를 작성해야

: 때문에 잘못된지도의

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

를, 내가 좋아하는가 someting를 사용할 수없는 이유는 무엇입니까?

편집 1

오라클 데이터베이스의 항목은 변경할 수 없습니다. 나는 단지 그들을 사용할 수 있습니다. 그러므로

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

이 작동하지 않습니다. "OracleTypes.STRUCT"를 사용하지 않는 즉시 예외가 발생하기 때문입니다. 내가

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

내가 예외를 얻을 때 outputOneSQLType의 내부는 "OracleTypeCOLLECTION"

형식의 개체가 보인다 InstantiationException: oracle.jdbc.oracore.OracleTypeCOLLECTION

@DazzaL : 나는 SQLDATA 인터페이스를 정의하려고합니다 . 어쩌면 그 해결책을 할 것이다

솔루션

  1. 준비된 문은 같은 것을해야한다 "package.procedure (...) 시작, 끝;" 및 하지 "{호출 package.procedure (...)})
  2. 하는 SQLData 인터페이스가 필요

@DazzaL :.!. 당신이 지배 들으

답변

5

당신은 SQLData를 정의해야 객체는이지도하는

문서 :. 예를 들어 http://docs.oracle.com/cd/E11882_01/java.112/e16548/oraarr.htm#JJDBC28574

:

,563,899,115

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

가 입력되었는지 확인하고 스트림의 순서가 불일치는 내부 표현의 오류를 줄 것이다로서, 오라클 유형과 동일 읽기/쓰기 :

2,093,210 지금 우리는 SQLDATA 인터페이스를 정의합니다.

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

들으을 다음과 같이

는 메인 클래스에서,이지도 것입니다. SQLDATA 인터페이스를 정의하려고합니다. 아마 그것이 해결책이 될 것입니다. –

+0

최고입니다, 고마워요! 내가 +1 – spiderman

+0

을 추가 할 수 있으면 좋겠다. 내 게시물도 올리 렴. - http://stackoverflow.com/questions/25253448/java-plsql-call-table-of-records-from-java/25274486#25274486 – spiderman

관련 문제