Mapping an Oracle stored procedure result to a custom Java type (class)
NickName:dsp_user Ask DateTime:2016-04-29T16:09:47

Mapping an Oracle stored procedure result to a custom Java type (class)

I have to call a stored procedure in Oracle (11g) that uses a single IN OUT parameter. This parameter is an Oracle custom type defined as

 CREATE OR REPLACE TYPE "SEPADD"."T_NAPRAVI_NALOG_TEST" IS OBJECT
 (
    I_INICIJALI              varchar2(3)  ,          
    I_STATUS                 number(1)        
 )

The actual type is more complex but I simplified it here for better readability. The Oracle procedure using this type (again simplified ) is defined as

  CREATE OR REPLACE PROCEDURE "SEPADD"."GETNALOGTESTPROC"(nalog in out T_NAPRAVI_NALOG_TEST )
IS   
      BEGIN       
  nalog.I_INICIJALI := 'PC';         
      nalog.I_STATUS := nalog.I_STATUS + 3; 
END;

The Oracle custom type is mapped to a Java class that implements the SQLData interface. (see https://docs.oracle.com/javase/tutorial/jdbc/basics/sqlcustommapping.html#implementing_sqldata)

 public class TNapraviNalog implements SQLData{

private int I_STATUS;
private String I_INICIJALI;
private String sql_type = "T_NAPRAVI_NALOG_TEST";
public String getSQLTypeName() {
        return sql_type;
    }
    public int getIStatus(){
     return this.I_STATUS;
}
    public String getIInicijali(){
        return this.I_INICIJALI;
    }
    public void setIInicijali(String in){
        I_INICIJALI = in;
    }
    public void setIStatus(int st){
        I_STATUS = st;
    }
    public void readSQL(SQLInput stream, String type)
        throws SQLException {
        sql_type = type;
        I_INICIJALI = stream.readString();
        I_STATUS = stream.readInt();

    }

    public void writeSQL(SQLOutput stream)
        throws SQLException {
        stream.writeString(I_INICIJALI);
        stream.writeInt(I_STATUS);          
    }
}

Now, from my JDBC code I call the Oracle stored procedure in the following way

    Object obj=null;
    ResultSet rs=null;
    CallableStatement stmt=null;
    TNapraviNalog n = null;
    try{

          sqlQuery = "{call getnalogtestproc(?)}";

          Map m = conn.getTypeMap();
          m.put("sepadd.T_NAPRAVI_NALOG_TEST", Class.forName("ib.easyorm.db.TNapraviNalog"));//this maps the Java class to the Oracle custom type
          conn.setTypeMap(m);

          stmt=conn.prepareCall(sqlQuery);
          stmt.registerOutParameter(1, Types.STRUCT, "T_NAPRAVI_NALOG_TEST");
          stmt.setObject(1, paramValues.get(0) ); //paramValues.get(0) returns an instance of TNapraviNalog class

          stmt.execute();    

          obj = stmt.getObject(1, m);

          //obj = stmt.getObject(1,TNapraviNalog.class); this method is not implemented in the JDBC driver

    }catch(Exception e){
          throw new EasyORMException(e);
    }finally{
          closeResources(rs,stmt);
    }
    return obj;

Now, the problem is that, while I can get the result returned by the stored procedure, the result is not converted to a Java class (TNapraviNalog) so I have to do that manually. I can successfully call the Oracle procedure with an instance of TNapraviNalog ( stmt.setObject(1, paramValues.get(0) ); ) but I can't get the result converted to TNapraviNalog. I really would like to be able to have something like

 TNapraviNalog nalog = stmt.getObject(1, m); 

However, this line will cause an exception ( java.lang.ClassCastException: oracle.sql.STRUCT cannot be cast to ib.easyorm.db.TNapraviNalog). I'm guessing that the JDBC driver isn't aware of the actual type returned by the stmt.getObject(1,m) and thus can't make the conversion.

Does anybody know if this can be done using either plain JDBC or Hibernate?

EDIT: The relevant code from an Oracle page (link given in cihan seven's answer)

Retrieving SQLData Objects from a Callable Statement OUT Parameter

Consider you have an OracleCallableStatement instance, ocs, that calls a PL/SQL function GETEMPLOYEE. The program passes an employee number to the function. The function returns the corresponding Employee object. To retrieve this object you do the following:

1.Prepare an OracleCallableStatement to call the GETEMPLOYEE function, as follows:

 OracleCallableStatement ocs = (OracleCallableStatement)conn.prepareCall("{ ? = call GETEMPLOYEE(?) }");

2.Declare the empnumber as the input parameter to GETEMPLOYEE. Register the SQLData object as the OUT parameter, with the type code OracleTypes.STRUCT. Then, run the statement. This can be done as follows:

 ocs.setInt(2, empnumber); 
 ocs.registerOutParameter(1, OracleTypes.STRUCT, "EMP_OBJECT"); 
ocs.execute(); 

3.Use the getObject method to retrieve the employee object. The following code assumes that there is a type map entry to map the Oracle object to the Java type Employee:

 Employee emp = (Employee)ocs.getObject(1); //my comment-->this doesn't seem to work

If there is no type map entry, then getObject would return an oracle.sql.STRUCT object. Cast the output to the STRUCT type, because the getObject method returns an instance of the generic java.lang.Object class. This is done as follows:

STRUCT emp = (STRUCT)ocs.getObject(1); 

Thank you

Copyright Notice:Content Author:「dsp_user」,Reproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/36932990/mapping-an-oracle-stored-procedure-result-to-a-custom-java-type-class

Answers
Luke Woodward 2016-04-29T19:56:03

The error appears to be in this line:\n\n m.put(\"sepadd.T_NAPRAVI_NALOG_TEST\", Class.forName(\"ib.easyorm.db.TNapraviNalog\"));//this maps the Java class to the Oracle custom type\n\n\nThis is the only line in which you are qualifying your T_NAPRAVI_NALOG_TEST type with the schema owner. You refer to it in two other places without the schema name.\n\nIf you're connecting to your database as the SEPADD user (it seems you are), you can remove the schema owner prefix sepadd. from this line. Alternatively, try changing the schema owner in the above line to upper-case.",


cihan adil seven 2016-04-29T09:06:20

You try to cast your Struct object to TNapraviNalog. But according to Oracle documentation you should first retrieve your struct as an java.sql.STRUCT object and then convert it to TNapraviNalog object.\n\ntry this:\n\njava.sql.Struct jdbcStruct = (java.sql.Struct)stmt.getObject(1, m);\n",


More about “Mapping an Oracle stored procedure result to a custom Java type (class)” related questions

Mapping an Oracle stored procedure result to a custom Java type (class)

I have to call a stored procedure in Oracle (11g) that uses a single IN OUT parameter. This parameter is an Oracle custom type defined as CREATE OR REPLACE TYPE "SEPADD"."T_NAPRAVI_NALOG_TEST" IS

Show Detail

How to map Java class to Oracle custom type to use as IN parameter in stored procedure?

I'm trying to use a custom object in oracledb as IN parameter for a procedure, but I'm having issues sending it from my java application I tried mapping the DTO class directly in query.

Show Detail

Oracle Stored Procedure and custom data type

I have an Oracle stored procedure which takes two parameters: a custom data type and a string. Calling the stored procedure in Oracle, I would do the following: EXECUTE MY_STORED_PROCEDURE(MYTYPE...

Show Detail

entity framework 3.5 and stored procedure result mapping

Using EF3.5 with Visual Studio 2010 (cannot upgrade to EF4 at this point - don't ask!). Wanting to create a stored procedure that aggregates some fields from some related tables and materialize the

Show Detail

Pass oracle object type to java stored procedure

Is is possible to pass oracle object type to java stored procedure. Here's what i have so far. Java stored procedure: create or replace and compile java source named Example as import java.sql.SQLD...

Show Detail

How to call stored procedure, having custom database type as a parameter, from hibernate?

I read tens of questions, javadoc, tutorials, myriads of posts, but the answer how to do this is still eluding me. Motivation: we need to pass List of entities to database to perform some optimized...

Show Detail

Custom object in Oracle stored procedure 11.2.0.4.0

I am calling an Oracle stored procedure in which I have an array of a custom type object. Below is my code. Type Object: create or replace type xx_wf_svc_ntf_attr_record is object (CITY varcha...

Show Detail

Executing Oracle stored procedure with XMLTYPE Output and capturing it in a SSIS variable

I am in desperate need of help with executing an Oracle stored procedure that takes an XML of Oracle XMLTYPE as input and Outputs an XML of Oracle XMLTYPE. I should be able to execute this Oracle

Show Detail

Pass table-type object as input parameter to Stored Procedure in Oracle from C#

I have stored procedure which accepts table-type as input parameter. How to pass object from c# code? create or replace TYPE CUSTOM_TYPE AS OBJECT ( attribute1 VARCHAR(10), attribute2 VARCHA...

Show Detail

Oracle stored procedure runs in the end of session in Informatica stored procedure transformation mapping

I created an Informatica mapping for which source is a text file and target is also a text file. I am calling an Oracle stored procedure by using connected stored procedure transformation and in th...

Show Detail