Вызов процедуры Oracle PL/SQL в Java с использованием CallableStatement с логическим параметром IN дает ошибку ORACLE PLS-00306:

У меня есть процедура pl/sql на Oracle 11g, которая имеет следующие параметры:

PROCEDURE validate_product
   ( product_id_in IN varchar2 , 
     username_in in varchar2, 
     source_in varchar2,    
     source_id_in varchar2 , 
     isEuProduct in boolean , 
     error_code out varchar2, 
     product_type out varchar2  
     )

Я пытаюсь вызвать вышеупомянутую хранимую процедуру из java, используя следующий код:

cstmt = getConnection().prepareCall("begin " + DBUtil.SCHEMANAME + ".PRODUCT_UTILITIES.validate_product(:1,:2,:3,:4,:5,:6,:7); end;");

cstmt.registerOutParameter(6, Types.CHAR); 
cstmt.registerOutParameter(7, Types.CHAR); 

cstmt.setString(1, productId);
cstmt.setString(2, username);
cstmt.setString(3, sourceName);
cstmt.setString(4, sourceId);
cstmt.setBoolean(5, isEUProduct);

cstmt.execute();

Типы переменных java - это все String, за исключением isEUProduct, который равен boolean. Всякий раз, когда я запускаю указанную выше программу, я получаю следующую ошибку:

PLS-00306: wrong number or types of arguments in call to validate_product ORA-06550: line 1, column 7: PL/SQL: Statement ignored"

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

Я полностью застрял в том, что я делаю неправильно. У меня возникли подозрения, что, возможно, я не задаю логический параметр правильно.

Любые идеи?

Ответ 1

Я был поражен, когда мы столкнулись с этим, но Драйвер JDBC Oracle не поддерживает передачу булевых файлов в Хранимые процедуры.... Я, я этого не делаю:)

Логические параметры в хранимых процедурах PL/SQL

Драйверы JDBC не поддерживают передачу параметров BOOLEAN в хранимые процедуры PL/SQL. Если процедура PL/SQL содержит значения BOOLEAN, вы можете обойти это ограничение, обернув процедуру PL/SQL второй процедурой PL/SQL, которая принимает аргумент как INT и передает его первой хранимой процедуре. Когда вызывается вторая процедура, сервер выполняет преобразование из INT в BOOLEAN.

Ответ 2

Я думаю, что здесь проблема

cstmt.registerOutParameter(6, Types.CHAR); 
cstmt.registerOutParameter(7, Types.CHAR); 

вы вызвали из java, как указано выше, но вы указали в параметре out процедуры как varchar2, что означает несоответствие типа данных.

Попробуйте этот код,

cstmt.registerOutParameter(6, Types.VARCHAR); 
cstmt.registerOutParameter(7, Types.VARCHAR); 

Я надеюсь, что это сработает.

Ответ 3

Существует простое обходное решение для этого ограничения, которое не требует процедуры обертки, просто оберните булевский параметр в PL/SQL в инструкции CASE и используйте Integer для привязки:

stmt = connection.prepareCall("begin" 
        +"  booleanFunc(par_bool => (CASE ? WHEN 1 THEN TRUE ELSE FALSE END)); "
        +"end;"
       );

// now bind integer, 1 = true, 0 = false
stmt.setInt(1, 0); // example for false

Вы можете обернуть Integer во время привязки другим способом, если ваш метод использует логическое значение, например:

// now bind integer, 1 = true, 0 = false
stmt.setInt(1, myBool ? 1 : 0); 

Ответ 4

Я подозреваю, что операторы out могут нуждаться в модификации следующим образом (так как тип выходных параметров - varchar2 в процедуре): -

cstmt.registerOutParameter(6, Types.VARCHAR); 
cstmt.registerOutParameter(7, Types.VARCHAR); 

Однако, если это не сработает, попробуйте изменить оператор prepareCall на следующее: -

cstmt = getConnection().prepareCall("{call " + DBUtil.SCHEMANAME + ".PRODUCT_UTILITIES.validate_product(?,?,?,?,?,?,?)}");