6

I've got, what started as a fairly complex stored procedure boils down to a very simple use case that doesn't seem to be working as i'm expecting.

The stored procedure now looks like this for my test:

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

I can call this stored procedure from java using the callable statement API

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

The above works as expeted. The method executes and completes successfully. Nows where it gets tricky. We've created a set of oracle object types to allow us to pass more complicated structures around similar to the following

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

if i simply change the procedure to accept these types as parameters, like this:

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

Oracle will break with PLS-00306: wrong number or types of arguments in call to 'CNV_CREATE_PERSON'

What gives? If i call this procedure from another procedure with null as the value, it works fine. Only calling it from the java API does it break.

I've been scouring the documentation for any solution and can't find one. Perhaps one of you wise and learned fellows could point me in the right direction.

Thanks

4

1 回答 1

11

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

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示例,但可以使用更简单的版本,如:

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

...但你只是通过就可以逃脱null

于 2014-09-08T17:43:19.083 回答