How to both send and receive Oracle collections via jdbc

1.6k views Asked by At

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.

0

There are 0 answers