Hi,

Till this morning I was sure that Oracle CURSOR types where fully supported in Cayenne (they are tested in our unit test suite after all). Now checking the relevant code, I must admit that the Modeler and mapping loader would not allow DB-specific types. Here is a workaround you can try. In your app somewhere on startup you can reset the type of the parameter to the oracle CURSOR:

Procedure p = ....;
Iterator it = p.getCallOutParameters().iterator();
while(it.hasNext()) {
   ProcedureParameter parameter = (ProcedureParameter) it.next();
   if("V_RESULT_CURSOR".equals(parameter.getName())) {
         parameter.setType(OracleTypes.CURSOR);
         break;
   }
}

Let us know if that worked. Also appreciate opening a Jira improvement request.

Thanks
Andrus



On May 15, 2007, at 4:38 PM, Marc Gabriel-Willem wrote:
Dear all,



We are trying to map the following oracle stored procedure using the
cayenne modeler.

Please find below all the details of the PL/SQL required to create the
stuff.



<<<< --- >>>>



create table tTest

(

            id          int NOT NULL,

            data      varchar2(200) NOT NULL,

            lastupdate         date NOT NULL,

            description        varchar2(200) NULL

);



CREATE OR REPLACE PACKAGE TestPackage

AS

-- Record Type definition

TYPE TestRecord IS RECORD

(

            id          int ,

            data      varchar2(200),

            lastupdate         date,

            description        varchar2(200)

);

-- Ref cursor definition
TYPE TestCursorRef IS REF CURSOR RETURN TestRecord;

END TestPackage;



-- stored proc fetching data

create or replace PROCEDURE spTestGet( v_result_cursor IN OUT

TestPackage.TestCursorRef )

as

BEGIN

            OPEN v_result_cursor FOR SELECT id, data, lastupdate,
description from tTest;

END ;



<<<< --- >>>>



Using JDBC, we are able to use that stored procedure using the following
instructions:



...

CallableStatement statement = db.prepareCall ("{ call spTestGet (?) }");

statement.registerOutParameter(1, OracleTypes.CURSOR);

statement.executeUpdate();

ResultSet rs = ((OracleCallableStatement)statement).getCursor(1);

while (rs.next())

{

            ...

}

...



Using the "reengineer database" modeler function, the following has been
automatically mapped:



<procedure name="SPTESTGET" schema="DDA">

            <procedure-parameter name="V_RESULT_CURSOR" type="OTHER"
direction="in_out"/>

</procedure>



Unfortunately, cayenne throws the following error:



INFO  QueryLogger: Detected and installed adapter:
org.apache.cayenne.dba.oracle.OracleAdapter

INFO  QueryLogger: {call DDA.SPTESTGET(?)} [bind: NULL]

INFO  QueryLogger: *** error.

java.sql.SQLException: Invalid column type

      at
oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134)

      at
oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:179)

      at
oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:269)

      at
oracle.jdbc.driver.OracleStatement.get_internal_type (OracleStatement.jav
a:6164)

      at
oracle.jdbc.driver.OracleCallableStatement.registerOutParameterBytes (Ora
cleCallableStatement.java:244)

      at
oracle.jdbc.driver.OracleCallableStatement.registerOutParameter (OracleCa
llableStatement.java:393)

      at
oracle.jdbc.driver.OracleCallableStatement.registerOutParameter (OracleCa
llableStatement.java:462)

      at
org.apache.cayenne.access.trans.ProcedureTranslator.setOutParam (Procedur
eTranslator.java:217)

            ...



We think the error provides from the fact that the parameter type is
probably incorrect. The modeler sets the type to "OTHER". As you could
see, using a standard JDBC call the type is set to "OracleTypes.CURSOR".
Is there a way to specify that "CURSOR" type too?



Thank you for your help.



Marc Gabriel


Reply via email to