来自Java的Oracle。对象参数的CallableStatement和Null?

时间:2014-09-08 16:50:44

标签: java oracle callable-statement

我已经开始了,一个相当复杂的存储过程开始归结为一个非常简单的用例,似乎没有像我期望的那样工作。

现在,对于我的测试,存储过程看起来像这样:

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

我可以使用可调用语句API

从java调用此存储过程
java.sql.CallableStatement stmt = conn.prepareCall("call proc_test(?)");
stmt.setObject(1,null);
stmt.execute();

以上作品已经过了。该方法执行并成功完成。现在它变得棘手。 我们已经创建了一组oracle对象类型,以允许我们传递更复杂的结构,类似于以下

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'

决裂

是什么给出的?如果我从另一个以null为值的过程调用此过程,它可以正常工作。只有从java API调用它才会中断。

我一直在搜索任何解决方案的文档,但找不到。也许你们中的一位聪明才智的学者可以指出我正确的方向。

由于

1 个答案:

答案 0 :(得分:7)

您需要使用the setNull() method来指定用户定义的类型:

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

将指定参数设置为SQL NULL。方法setNull的此版本应该用于用户定义的类型和REF类型参数。用户定义类型的示例包括:STRUCT,DISTINCT,JAVA_OBJECT和命名数组类型。

     

注意:为了便于移植,应用程序必须在指定NULL用户定义或REF参数时提供SQL类型代码和完全限定的SQL类型名称。在用户定义类型的情况下,名称是参数本身的类型名称。对于REF参数,名称是引用类型的类型名称。

所以在你的情况下:

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

如果你只是传递null,那么它不知道它代表什么类型,也不能进行任何隐式转换。这确实意味着您的代码需要根据您的Java对象是否为空而进行分支,以便根据需要调用setNull()setObject()

您也应该在setNull()示例中使用varchar2,但可以使用the simpler version,因为:

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

...但你只是通过了null