Waheem Rahman

February 23, 2008

Java: Passing arrays to a stored procedure with PLSQL Table Type

Filed under: Project — arwaheem @ 1:08 am

Not all PL/SQL arrays can be direcly accessed using JDBC. Procedures or Functions that take arrays and are declared inside packages instead of with “CREATE TYPE” can not be called using JDBC. This is a limitation of Oracle.
Approach to solve this issue:
1. Write an additonal wrapper procedure that converts an array created with CREATE TYPE into the format required by your procedure
If you can not change the procedure itself  or it is already used by a large base of existing code you may have to go with option 2 of writing an additional wrapper procedure that takes parameters usable by JDBC:

Original Code: 
Create or Replace Package tms_user_autocode IS
Type DeriveValuesREC IS RECORD (
DefLevelId number(10),
ColumnName VARCHAR2(30),
ValueText tms_dict_contents.term%TYPE,
ClassificationCode VARCHAR2(1));

Type DeriveValuesTAB is TABLE of DeriveValuesREC INDEX BY BINARY_INTEGER;

FUNCTION ClassifyTerm(
pDefDictionaryId     IN  NUMBER
pDefDomainId         IN  NUMBER
pTerm                IN  VARCHAR2
pSourceTermId        IN  NUMBER
pOccurrenceId        IN  NUMBER
pSourceTermAltKey    IN  VARCHAR2
pNoOmissionFlag      IN  VARCHAR2
pDefIntegrationKey   IN  VARCHAR2
pDefInstanceName     IN  VARCHAR2
pXArea       IN  NUMBER
pExtValue1           IN  VARCHAR2
pExtValue2           IN  VARCHAR2
pExtValue3           IN  VARCHAR2
pExtValue4           IN  VARCHAR2
pExtValue5           IN  VARCHAR2
pExtValue6           IN  VARCHAR2
pExtValue7           IN  VARCHAR2
pExtValue8           IN  VARCHAR2
pOmissionStatus      IN OUT VARCHAR2
pOmissionOwner       IN OUT VARCHAR2
pActionText          IN OUT VARCHAR2
pVTAid               OUT NUMBER
pSearchID            OUT NUMBER
pDeriveValues        IN OUT tms_user_autocode.DeriveValesTAB) RETURN PLS_INTEGER

END tms_user_autocode;
Wrapper Procedure:

CREATE OR REPLACE
PROCEDURE CTRM_tms_user_autocode
(jDefDictionaryId     IN  NUMBER,
jDefDomainId         IN  NUMBER,
jTerm                IN  VARCHAR2,
jSourceTermId        IN  NUMBER,
jOccurrenceId        IN  NUMBER,
jSourceTermAltKey    IN  VARCHAR2,
jNoOmissionFlag      IN  VARCHAR2,
jDefIntegrationKey   IN  VARCHAR2,
jDefInstanceName     IN  VARCHAR2,
jXArea       IN  NUMBER,
jExtValue1           IN  VARCHAR2,
jExtValue2           IN  VARCHAR2,
jExtValue3           IN  VARCHAR2,
jExtValue4           IN  VARCHAR2,
jExtValue5           IN  VARCHAR2,
jExtValue6           IN  VARCHAR2,
jExtValue7           IN  VARCHAR2,
jExtValue8           IN  VARCHAR2,
jOmissionStatus      IN OUT VARCHAR2,
jOmissionOwner       IN OUT VARCHAR2,
jActionText          IN OUT VARCHAR2,
jSearchID            OUT NUMBER,
jVTAid               OUT NUMBER,
jDeriveValues        IN OUT CTRM_DeriveValuesTAB
returnValue       OUT Number) AS

l_array tms_user_autocode.DeriveValuesTAB;
l_record tms_user_autocode.DeriveValuesREC;
 
  BEGIN
– Load our JDBC table into the PL/SQL one… 
  l_array.delete;
  FOR i IN jDeriveValues.FIRST
        .. jDeriveValues.LAST LOOP
  l_record := NULL;

  l_record.DefLevelId  := jDeriveValues(i).DefLevelId;
  l_record.ColumnName := jDeriveValues(i).ColumnName;
  l_record.ValueText := jDeriveValues(i).ValueText;
  l_record.ClassificationCode := jDeriveValues(i).ClassificationCode;
  l_array(i) := l_record;
 
  END LOOP;
 returnValue := tms.TMS_user_AUTOCODE.ClassifyTerm(
              jDefDictionaryId
            , jDefDomainId
            , jTerm
            , jSourceTermId
            , jOccurrenceId
            , jSourceTermAltKey
            , jNoOmissionFlag
            , jDefIntegrationKey
            , jDefInstanceName
            , jXArea
            , jExtValue1
            , jExtValue2
            , jExtValue3
            , jExtValue4
            , jExtValue5
            , jExtValue6
            , jExtValue7
            , jExtValue8
            , jOmissionStatus
            , jOmissionOwner
            , jActionText
            , jSearchId
            , jVTAid
            ,l_array
            );
           
  FOR i IN l_array.FIRST .. l_array.LAST LOOP
    jDeriveValues(i).DefLevelId   := l_array(i).DefLevelId;
    jDeriveValues(i).ColumnName  := l_array(i).ColumnName;
    jDeriveValues(i).ValueText  := l_array(i).ValueText;
    jDeriveValues(i).ClassificationCode  := l_array(i).ClassificationCode;
   
  END LOOP;

END;

Java program :

 import java.sql.*;

import oracle.jdbc.OracleTypes;
 import oracle.sql.ARRAY;
import oracle.sql.ArrayDescriptor;
import oracle.sql.STRUCT;
import oracle.sql.StructDescriptor;
 
 public class Test {
  public static void main(String[] args) throws SQLException {
   CallableStatement proc = null;
     try {
      Connection conn=null;
 DriverManager.registerDriver (new oracle.jdbc.OracleDriver());
 //Establish a connection
  conn = DriverManager.getConnection
     (“jdbc:oracle:oci8:@123.WORLD”,
                                   “scott”, “tiger);
  System.out.println(“connection success0″);
 
  int DictId = 8;
  int DomainId = 1;
  String Term = “BLOOD”;
  int SourceId=0;
  String pOccurrenceId=”0″;
  String pSourceTermAltKey =”";
  String pDefIntegrationKey=”CTRM”;
  String pDefInstanceName=”OCP451.GROTON.PFIZER.COM”;
  int pXArea=1;
  String Flag=”N”;
  String pExtValue1=”";
  String pExtValue2=”";
  String pExtValue3=”";
  String pExtValue4=”";
  String pExtValue5=”";
  String pExtValue6=”";
  String pExtValue7=”";
  String pExtValue8=”";
  String ActionText=”";
  int returnValue=0;
  int sid=0;
  String oStat=”";
  String oOwner=”";
  //String xsystem=”";
  int vtaid=0;
 
 
   // create the ARRAY by calling the constructor
  

    System.out.println(“connection success1.1″);
//First, declare the Object arrays that will store the data.
  Object [] p1recobj = {new Integer(811),”TERM”,”",”"};
  Object [] p2recobj  = {new Integer(811),”DICT_CONTENT_CODE”,”",”"};
  Object [] p3recobj = {new Integer(812),”TERM”,”",”"};
  Object [] p4recobj = {new Integer(812),”DICT_CONTENT_CODE”,”",”"};
  System.out.println(“connection success1.2″);
//Declare the Object Arrays to hold the STRUCTS.
  Object [] p1arrobj;
  //Object [] p2arrobj;
  System.out.println(“connection success1.3″);
  //  Declare two descriptors, one for the ARRAY TYPE
  //  and one for the OBJECT TYPE.
  StructDescriptor desc1 = StructDescriptor.createDescriptor(“CTRM_DERIVEVALUESREC”, conn);
  ArrayDescriptor desc2 = ArrayDescriptor.createDescriptor(“CTRM_DERIVEVALUESTAB”, conn);
  System.out.println(“connection success1.4″);
  //  Create the STRUCT objects to associate the host objects
  //  with the database records.
     STRUCT p1struct = new STRUCT(desc1,conn,p1recobj);
     STRUCT p2struct = new STRUCT(desc1,conn,p2recobj);
     STRUCT p3struct = new STRUCT(desc1,conn,p3recobj);
     STRUCT p4struct = new STRUCT(desc1,conn,p4recobj);
     System.out.println(“connection success1.5″);
  //  Initialize the Input array object – to an array of STRUCT Objects.
     p1arrobj = new Object []{p1struct,p2struct,p3struct,p4struct};
     System.out.println(“connection success1.6″);
  //  Set up the ARRAY object.
     ARRAY  p1arr = new ARRAY(desc2,conn,p1arrobj);
   //  ARRAY  p2arr;
     System.out.println(“connection success1.7″); 
  proc = conn.prepareCall(“{ call CTRM_tms_user_autocode(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}”);
     System.out.println(“connection success1.8″);    
  proc.setInt(1, DictId);
  proc.setInt(2, DomainId);
  proc.setString(3, Term);
  proc.setInt(4, SourceId);
  proc.setString(5, pOccurrenceId);
  proc.setString(6, pSourceTermAltKey);
  proc.setString(7, Flag);
  proc.setString(8, pDefIntegrationKey);
  proc.setString(9, pDefInstanceName);
  proc.setInt(10, pXArea);
  proc.setString(11, pExtValue1);
  proc.setString(12, pExtValue2);
  proc.setString(13, pExtValue3);
  proc.setString(14, pExtValue4);
  proc.setString(15, pExtValue5);
  proc.setString(16, pExtValue6);
  proc.setString(17, pExtValue7);
  proc.setString(18, pExtValue8);
  proc.setString(19, oStat);
  proc.setString(20, oOwner);
  proc.setString(21, ActionText);
  proc.setInt(22,sid);
  proc.setInt(23, vtaid);
  proc.setArray(24,p1arr);
  proc.setInt(25,returnValue);
//Registering OUT parameter
  proc.registerOutParameter (19, Types.VARCHAR);
  proc.registerOutParameter (20, Types.VARCHAR);
  proc.registerOutParameter (21, Types.VARCHAR);
  proc.registerOutParameter (22, Types.INTEGER);
  proc.registerOutParameter (23, Types.INTEGER);
  proc.registerOutParameter(24,OracleTypes.ARRAY,”CTRM_DERIVEVALUESTAB”);
  proc.registerOutParameter (25, Types.INTEGER);
  System.out.println(“connection success1.9″);
  proc.execute();
  System.out.println(“connection success2″);
//  Associate the returned arrays with the ARRAY objects.
  oStat=proc.getString(19);
  oOwner=proc.getString(20);
  ActionText=proc.getString(21);
  sid = proc.getInt(22);
  vtaid = proc.getInt(23);
  p1arr = (ARRAY) proc.getArray(24);
  returnValue=proc.getInt(25);
  System.out.println(“connection success2.1″);
//Get the data back into the data arrays.
  p1arrobj = (Object [])p1arr.getArray();
  System.out.println(“connection success2.2″);
//  Get the data records from each array element (which is of type STRUCT).
  p1recobj = ((STRUCT)p1arrobj[0]).getAttributes();
  p2recobj = ((STRUCT)p1arrobj[1]).getAttributes();
  p3recobj = ((STRUCT)p1arrobj[2]).getAttributes();
  p4recobj = ((STRUCT)p1arrobj[3]).getAttributes();
  System.out.println(“connection success2.3″);
//Show the results:
  System.out.println(“returnValue “+returnValue);
  System.out.println(“ActionText “+ActionText);
  System.out.println(“OmissStat “+oStat);
  System.out.println(“OmissOwner “+oOwner);
  System.out.println(“SearchID “+sid);
  System.out.println(“VTAID “+vtaid);
  System.out.println(“First Object is now “+p1recobj[0]+” and “+p1recobj[1]+” and “+p1recobj[2]+” and “+p1recobj[3]);
  System.out.println(“                    “+p2recobj[0]+” and “+p2recobj[1]+” and “+p2recobj[2]+” and “+p2recobj[3]);
  System.out.println(“Second Object is now “+p3recobj[0]+” and “+p3recobj[1]+” and “+p3recobj[2]+” and “+p3recobj[3]);
  System.out.println(“                    “+p4recobj[0]+” and “+p4recobj[1]+” and “+p4recobj[2]+” and “+p4recobj[3]);
 

  
         conn.commit();
 
     } catch (Exception e) {
        
         System.out.println(“e>”+e);
     
     } finally {
         if (proc != null)
             proc.close();
     }
 }
}

Site Meter

No Comments Yet »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a comment

Blog at WordPress.com.