4

이 문제를 해결하는 데 너무 가깝지만 분명히 누락되었습니다. 내 요구 사항은 JDBC에서 오라클의 저장 프로 시저를 호출하는 것입니다. 저장 프로시 듀어는 사용자 정의 Oracle 오브젝트 1 개를 INput으로, 또 다른 사용자 정의 Oracle 오브젝트를 OUTput으로 취합니다. INput 및 OUTput 객체는 원시 Oracle 데이터 유형과 다른 사용자 정의 객체 집합의 컬렉션을 혼합합니다. 나는 성공적으로 저장 프로 시저를 호출하고 INput 및 OUTput 객체의 콜렉션 유형에 NULL을 설정하는 한 결과를 다시 얻을 수있다. 오라클 객체 목록에 ArrayDescriptor를 만들어 저장 프로 시저에 보내려고하면로드 블록이 계속 발생합니다. 그래서 Array를 INput 객체로 설정하고 CallableStatement로 설정하는 방법에 대한 도움이 필요합니다. 저장 프로 시저에 직접 입력으로 원시 형식 및 배열을 보낼 수있는 방법을 알고 있습니다. 그러나 우리가 나중에 절차에 10 개의 추가 필드를 보내야하기 때문에 그렇게하지 않으려 고합니다. 메소드 서명에 추가하지 않으려합니다. 다음은 클래스 목록입니다. 또한 아래 코드에는 컴파일 오류가 없습니다. 오라클의복잡한 입력 및 출력 유형을 가진 JDBC에서 Oracle 저장 프로 시저를 호출하십시오.

패키지 :

create or replace TYPE  ARR_OBJ_1_NT AS TABLE OF ARR_OBJ_1_OBJ; 
: 입력 개체
의 일환으로

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

배열 개체 : 저장 프로 시저에 대한

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

입력 객체 입력 개체의 17,451,515,

사용자 정의 된 개체 부분 :

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. 객체 스키마 수준에서 선언하고 DB를 사용자가 액세스하는 데 사용할 수 있습니다 그것은 실제로 저장 프로 시저에 호출을 실행합니다. 2. 더 많은 공간이 필요하므로 여기에 해당 Java 객체를 모두 포함하지 않았습니다. SQLData 인터페이스를 구현하고 유형 이름이 DB 이름과 일치합니다. read 및 writeSQL 메소드는 getString, getArray 및 해당 setter 메소드를 사용합니다.

+0

당신은 올바른 길을 향하고 있습니다. 당신이 받고있는 예외를 게시 할 수 있습니까? – Nick

+0

TESTDATA_OUT_OBJ 선언은 어디에 있습니까? – Nagh

+0

이봐,이 대답을 얻었 니? –

답변

0

이것은 매우 오래된 접근법입니다. 왜 "Oradata"및 "Oradatum"인터페이스를 사용하지 않습니까? 많은 노력을 줄일 수 있습니다.

당신의 접근법은 많은 오류를 남기 때문에 스트림을 적절한 방식으로 읽고 필드 순서를 스스로 점검해야합니다. 까다로울 수 있습니다. Oradata 접근 방식이 당신을 위해 그것을 할 것입니다.

접근 방식에 따라 코드가 명확하지 않습니다. 그러나 개요를 제공하기 위해 StructDescriptor는 oracle 레코드 유형으로 매핑하고 ArrayDescriptor는 달성하려는 대상에 대해 혼동 스럽지만 코드에서 oracle 테이블 유형으로 매핑합니다.

더 명확하게 할 수 있다면 도와 드리겠습니다.