Оракул из Явы. CallableStatement и Null для параметра объекта?

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

Теперь хранимая процедура для моего теста выглядит так:

CREATE OR REPLACE PROCEDURE proc_test(
v_someString varchar2
                      ) as
BEGIN
    dbms_output.put_line('test');
END;

Я могу вызвать эту хранимую процедуру из java, используя вызываемый оператор API

java.sql.CallableStatement stmt = conn.prepareCall("call proc_test(?)");
stmt.setObject(1,null);
stmt.execute();

Вышеупомянутое работает, как и ожидалось. Метод выполняется и завершается успешно. Теперь, когда это становится сложным. Мы создали набор типов объектов оракула, чтобы позволить нам передавать более сложные структуры, подобные следующим

CREATE OR REPLACE
type SOMETYPE_TYPE force  UNDER BASE_TYPE (value varchar2(255),
CONSTRUCTOR FUNCTION SOMETYPE_TYPE RETURN SELF AS RESULT) NOT FINAL;

если я просто изменю процедуру, чтобы принять эти типы в качестве параметров, например:

CREATE OR REPLACE PROCEDURE proc_test(
v_someString SOMETYPE_TYPE 
                      ) as
BEGIN
    dbms_output.put_line('test');
END;

Oracle порвет с PLS-00306: wrong number or types of arguments in call to 'CNV_CREATE_PERSON'

Что дает? Если я вызываю эту процедуру из другой процедуры с нулевым значением в качестве значения, она работает нормально. Только вызывая его из java API, он ломается.

Я искал документацию для любого решения и не могу найти его. Возможно, кто-нибудь из вас, мудрых и образованных людей, укажет мне правильное направление.

Спасибо


person Beta033    schedule 08.09.2014    source источник
comment
Когда вы используете TYPEs в параметрах, используете ли вы STRUCT в вашем JDBC?   -  person Maheswaran Ravisankar    schedule 08.09.2014
comment
Вы не можете просто отправить null вместо типа, вместо этого упакуйте пустую структуру!   -  person Maheswaran Ravisankar    schedule 08.09.2014
comment
@Maheswaran Ravisankar Итак, вы можете передать null как varchar2, int, blob, clob или любой другой встроенный тип, но не ваши собственные типы? Должен быть какой-то способ обойти это. Я не знаю, почему оракул сделал бы это единственным вариантом, кроме того, я могу просто вызвать процедуру с нулевым значением из другой процедуры, такой как proc_test(null);   -  person Beta033    schedule 08.09.2014


Ответы (1)


Вам нужно использовать метод setNull() для указания пользовательского типа:

void setNull(String parameterName,
           int sqlType,
           String typeName)
             throws SQLException

Задает назначенному параметру значение SQL NULL. Эту версию метода setNull следует использовать для пользовательских типов и параметров REF-типа. Примеры определяемых пользователем типов включают: STRUCT, DISTINCT, JAVA_OBJECT и типы именованных массивов.

Примечание. Чтобы быть переносимыми, приложения должны указывать код типа SQL и полное имя типа SQL при указании определяемого пользователем параметра NULL или параметра REF. В случае определяемого пользователем типа имя является именем типа самого параметра. Для параметра REF имя является именем типа, на который ссылаются.

Итак, в вашем случае:

stmt.setNull(1, java.sql.Types.STRUCT, "SOMETYPE_TYPE");

Если вы просто передадите null, то он не будет знать, какой тип он представляет, и не сможет выполнить какое-либо неявное преобразование. Это означает, что ваш код должен разветвляться в зависимости от того, является ли ваш объект Java нулевым или нет, чтобы вызвать setNull() или setObject() в зависимости от ситуации.

Вы действительно должны использовать setNull() для своего примера varchar2, но можете использовать более простая версия, например:

stmt.setNull(1, java.sql.Types.VARCHAR);

... но вам сойдет с рук просто передача null.

person Alex Poole    schedule 08.09.2014
comment
Это работает! Я немного поигрался с SetNull, но использовал неправильный перегруженный метод setNull(int parameterIndex, int sqlType). Что для меня вызвало просто другой набор ошибок. Спасибо за руководство. - person Beta033; 10.09.2014