我已经开始了,一个相当复杂的存储过程开始归结为一个非常简单的用例,似乎没有像我期望的那样工作。
现在,对于我的测试,存储过程看起来像这样:
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调用它才会中断。
我一直在搜索任何解决方案的文档,但找不到。也许你们中的一位聪明才智的学者可以指出我正确的方向。
由于
答案 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
。