简体   繁体   中英

How can I call an Oracle stored procedure with JDBC/Spring where some of the parameter types are user defined?

I'm trying to call an Oracle stored procedure from my Java program. I'm using JDBC and Spring's StoredProcedure. A couple of the parameters are user defined types and I need to know how to pass them in.

In particular what type should I specify in the parameter map (ie which of java.sql.Types.* )? And what Java type should I use? The problem types are defined like this:

type MyDoubles as varray(50000) of double precision
type MyStrings as varray(50000) of varchar2(2000)

First hit in Google seems to show how to bind parameters of type VARRAY: http://www.devx.com/tips/Tip/22034 . The examples in this document use a prepared statement, but for a stored procedure it should work just the same.

Here's an excerpt showing the basic concept:

String arrayElements[] = { "Test3", "Test4" };
PreparedStatement ps =
    conn.prepareStatement ("insert into sample_varray_table values (?)");

ArrayDescriptor desc = ArrayDescriptor.createDescriptor("STRING_VARRAY", conn);
ARRAY newArray = new ARRAY(desc, conn, arrayElements);
((OraclePreparedStatement)ps).setARRAY (1, newArray);

ps.execute ();

To clarify here are a few FQDNs:

  • oracle.sql.ArrayDescriptor
  • oracle.sql.ARRAY
  • oracle.jdbc.OraclePreparedStatement

Why are users passing 50,000 instances of doubles and strings - so Oracle can perform a calculation?

This seems backwards to me. If users already have all that day, perhaps Java can perform that calculation. If you really want Oracle to do it, I'd say the data should already be resident within the database and not passed in.

Wouldn't both be java.sql.Type.ARRAY?

You can indeed use objects from the Oracle JDBC driver as suggested by Philipp. Most users wind up creating utility methods to wrap that logic. Or they use the Spring mapper classes. Still, there is a lot of manual work to do.

A different approach is to use the upcoming version 1.5.4 of jOOQ - an open source library I'm developing - where arrays are supported uniformely. So when you have your types:

type MyDoubles as varray(50000) of double precision
type MyStrings as varray(50000) of varchar2(2000)

Then jOOQ would generate classes such as

public class MyDoubles extends ArrayRecordImpl<Double> { /* ... */ }
public class MyStrings extends ArrayRecordImpl<String> { /* ... */ }

Your stored procedures might look like this:

PROCEDURE MY_PROC1 (d IN  MyDoubles, s IN  MyStrings);
PROCEDURE MY_PROC2 (d IN  MyDoubles, s OUT MyStrings);
PROCEDURE MY_PROC3 (d OUT MyDoubles, s OUT MyStrings);

And jOOQ would generate another Java class such as

public class Procedures {

    // Invoke procedure MY_PROC on JDBC Connection c with VARRAY arguments
    public static void myProc1(Connection c, MyDoubles d, MyStrings s);

    // The OUT parameter is mapped to a method return value
    public static MyStrings myProc2(Connection c, MyDoubles d);

    // MyProc3 is a wrapper for both OUT parameters
    public static MyProc3 myProc3(Connection c);
}

With generated code artifacts, calling stored procedures with UDT, VARRAY parameters is as easy as it can be. And with source code generation, you can change objects (eg your types, or your procedures) in your database schema, and your Java classes will immediately reflect that change.

Check out the manual at http://www.jooq.org/manual/META/PROCEDURE/ for more details

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM