4

Я так близко решаю этот вопрос, но я, очевидно, что-то пропустил. Мое требование - вызвать хранимую процедуру в Oracle из JDBC. Хранимая процедура принимает 1 пользовательский объект Oracle как INput и другой пользовательский объект Oracle как OUTput. Объекты INput и OUTput сочетают как примитивные типы данных Oracle, так и коллекцию другого набора пользовательских объектов. Я успешно могу вызвать хранимую процедуру и вернуть результаты, пока я устанавливаю NULL для типов коллекций в объектах INput и OUTput. Если я попытаюсь создать ArrayDescriptor для списка объектов Oracle, чтобы отправить его в хранимую процедуру, я продолжаю бить блокпосты. Поэтому мне нужна помощь в том, как установить Array на объект INput и установить его в CallableStatement. Обратите внимание: я знаю, как я могу отправить примитивный тип и массив как прямые входы в хранимую процедуру. Но я не хочу идти так, как мы позже должны отправить 10 дополнительных полей в процедуру, я не хочу добавлять их в подпись метода. Вот список классов. Кроме того, для приведенного ниже кода ошибок компиляции нет.Вызов Oracle Хранимая процедура из JDBC со сложным типом ввода и вывода

Пакет в оракула:

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

UserDefined часть Объект ввода объекта:

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 и соответствующие методы настройки.

+0

Вы направляетесь по правой тропе. Можете ли вы опубликовать исключения, которые вы получаете? – Nick

+0

Где декларация TESTDATA_OUT_OBJ? – Nagh

+0

Эй, ты получил ответ на это? –

ответ

0

Это очень старый подход, почему вы не используете интерфейс «Oradata» и «Oradatum»? Это сэкономит массу усилий.

Ваш подход оставляет много ошибок для ошибки, вам нужно будет прочитать поток надлежащим образом и самим проверить порядок полей, которые могут быть сложными. Подход Орадаты сделает это за вас.

Подойдя к вашему подходу, ваш код не очень ясен. Но для того, чтобы дать обзор, StructDescriptor будет отображать тип записи оракула, а ArrayDescriptor будет отображаться в виде таблицы oracle, из вашего кода я путаюсь о том, чего вы пытаетесь достичь.

Я могу помочь, если вы можете сделать это более понятным.