简体   繁体   中英

how to reference an oracle pl/sql out parameter of table%rowtype as an object in java

In Oracle 11g I have a table survey with properties id , title , and message . The stored procedure below gets a single record based on a provided ID and stores it in the provided OUT parameter.

create or replace procedure get_survey(arg_id number, obj_survey out survey%rowtype) is
begin
  select * into obj_survey from survey where id = arg_id;
end get_survey;

I need to call this stored procedure from Java and I know I can begin with a CallableStatement , but how do I pass the OUT parameter from Java considering it has to be of type survey%rowtype ? I know I can use a cursor instead but I think that's not good practice since I'm retrieveing only one row. Also, I need to create a Survey object (POJO) from the OUT parameter and return it from the method. Here's how far I've currently gotten in the code:

public Survey getSurvey(int id) throws SQLException {
  CallableStatement stmt = conn.prepareCall("begin get_survey(?, ?); end;");
  stmt.setInt(1, id);
  stmt.registerOutParameter(2, OracleTypes.[okay what do i put here?]); // not sure about this line either
  stmt.execute();

  // get the out parameter, convert it to a Survey object type and return it

}

"rowtype" here is an Oracle PL/SQL-specific type, I don't think it would be supported by JDBC. A quick search of the oracle forums (google "jdbc rowtype site:oracle.com") suggests the same. You're probably better off returning a cursor, or just execute the SQL from JDBC directly.

Unfortunately, you cannot serialise a PL/SQL RECORD type over JDBC, but you can work around this limitation by executing an anonymous PL/SQL block like this:

DECLARE
  obj_survey survey%rowtype;
BEGIN
  get_survey(?, obj_survey);

  ? := obj_survey.id;
  ? := obj_survey.x;
  ? := obj_survey.y;
  ...
  -- continue this for all attributes in survey
END;

You can now use the following CallableStatement :

try (CallableStatement s = conn.createCall(" [ ... above PL/SQL ... ] ")) {
    s.setInt(1, id);
    s.registerOutParameter(2, Types.INTEGER);
    s.registerOutParameter(3, Types.VARCHAR);
    s.registerOutParameter(4, Types.DATE);
    ...
    // Repeat for all attributes

    s.execute();

    int id = s.getInt(2);
    String x = s.getString(3);
    Date y = s.getDate(4);
    ...
    // Repeat for all attributes
}

I've recently written about this technique in a blog post , which also explains how these PL/SQL blocks can be generated automatically for all PL/SQL RECORD types.

Just an idea, You could make your function as a piplined function and then retrieve the data as if it was a table. here is some examples of piplined functions

http://www.akadia.com/services/ora_pipe_functions.html

cstmt = conn.getNewCallableStatement("{call MY_PLSQL_PACKAGE.MY_PROC(?,?,?)}");
       cstmt.setString(1, stringOutput1);
       cstmt.setString(2, stringOutput2);
       cstmt.registerOutParameter(3, OracleTypes.CURSOR);
       cstmt.execute;

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