0

I'm trying to call a stored procedure that receives several string types and one table of objects, and returns a table of objects. Here are my types:

create type recipientlist as object (
    precedence varchar2(2), name varchar2(128), msgType varchar2(3));
create type recipientlist_t as TABLE of recipientlist;
create type recipientclient  as object (pla varchar2(128), client varchar2(20));
create type recipientclientlist_t as table of recipientclient;

Here's my code:

import java.util.ArrayList;
import java.sql.Array;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.sql.SQLException;
import java.sql.Types;

import oracle.jdbc.*;
import oracle.jdbc.oracore.OracleTypeCOLLECTION;
import oracle.jdbc.pool.OracleDataSource;
import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;



class OadUtilities {

    public static void main(String[] args) throws SQLException{

         OracleDataSource ods = new OracleDataSource();
         ods.setURL("jdbc:oracle:thin:username/password@localhost:1521/myservicename");

         Connection conn = ods.getConnection();
         CallableStatement proc =
         conn.prepareCall("{call extractAttributes(?,?,?,?,?,?)}");

         ArrayDescriptor arrDesc1 =
                    ArrayDescriptor.createDescriptor("RECIPIENTLIST_T", conn);
         <del>ArrayDescriptor arrDesc2 =
                    ArrayDescriptor.createDescriptor("RECIPIENTCLIENTLIST_T", conn);</del>
         // instead of the ArrayDescriptor I use a StructDescriptor with ResultSetMetaData
         StructDescriptor structDesc =
        StructDescriptor.createDescriptor("RECIPIENTCLIENT", conn);
     ResultSetMetaData metaData = structDesc.getMetaData();

         String[] myRecipientData = {"TO","ADDRESS","LETTER"};
         String[][] myRecipientDataArray = { myRecipientData };
         Array myRecipientList = new ARRAY(arrDesc1, conn, myRecipientDataArray);

         <del>String[] myClientData = new String[2];
         String[][] myClientDataArray = { myClientData };
         Array myClientList = new ARRAY(arrDesc2, conn, myClientDataArray);</del>

         proc.setString(1, "X");
         proc.setString(2, "ABC DEF GHI");
         proc.setString(3, "JK LM NO");
         proc.setString(4, "PQ");
         proc.setArray(5, myRecipientList);
         proc.registerOutParameter(6, Types.ARRAY);
         <del>proc.setArray(6, myClientList);</del>
         proc.registerOutParameter(6, Types.ARRAY, "RECIPIENTCLIENTLIST_T");

         ResultSet rset = proc.executeQuery();

         <del>while (rset.next()) {
             System.out.println("ADDRESSEE = " + rset.getArray(1));
             System.out.println("CLIENT = " + rset.getArray(2));
         } </del>

     // elements are java.sql.Structs
     Object[] data = (Object[]) ((Array) proc.getObject(6)).getArray();
     for(Object tmp : data) {
         Struct row = (Struct) tmp;
     // Attributes are index 1 based...
     int idx = 1;
     for(Object attribute : row.getAttributes()) {              
         System.out.println(metaData.getColumnName(idx) + " = " + attribute);
         ++idx;
     }
     System.out.println("---");      

      }

             // close the result set, the statement and connect
             rset.close();
             conn.close();

    }

}

When I run it, I get this:

Exception in thread "main" java.sql.SQLException: ORA-03115: unsupported network datatype or    representation

at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
at oracle.jdbc.driver.T4CCallableStatement.doOall8(T4CCallableStatement.java:202)
at oracle.jdbc.driver.T4CCallableStatement.executeForRows(T4CCallableStatement.java:1005)
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307)
at       oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3493)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1491)
at oadUtilities.OadUtilities.main(OadUtilities.java:50)

I suspect that something is not quite right with the array descriptors, but they all built correctly, so maybe it's the null array I'm passing in for the return? Haven't found anything Googling that showed complex collections in and out, so I'm at a loss.

UPDATE: after looking at the code at the site I mention below, I wrote this up and it works perfectly.

  • Is the 6th parameter of `extractAttributes` an `IN OUT` parameter or just `OUT`? If it's just `OUT`, then don't call `setArray` at all for position 6. – rgettman Mar 17 '14 at 21:35
  • possible duplicate of [How do I get table user defined types from PLSQL as out param?](http://stackoverflow.com/questions/9630359/how-do-i-get-table-user-defined-types-from-plsql-as-out-param) – Bob Jarvis - Слава Україні Mar 17 '14 at 23:23
  • possible duplicate of [How to both send and receiver oracle collections via jdbc](http://stackoverflow.com/questions/6410452/fetch-oracle-table-type-from-stored-procedure-using-jdbc) – Bob Jarvis - Слава Україні Mar 17 '14 at 23:25
  • I found most of my answer at this web site: http://info.michael-simons.eu/2012/07/24/how-to-retrieve-tables-of-custom-object-types-with-jdbc/ It gave me most of the answer, and I was able to figure out the rest. I put the new code up in the box with the original post. – James Schrumpf Mar 19 '14 at 01:30

0 Answers0