1

I am using Oracle 12g and am trying to get a ResultSet from a SYS_REFCURSOR

I have a procedure with the following signature:

CREATE OR REPLACE PROCEDURE proc_search(user IN VARCHAR2, res OUT SYS_REFCURSOR)

This is the Java JDBC code I am using:

try {
    CallableStatement cstmt = con.prepareCall("exec proc_search(?, ?)");
    cstmt.setString(1, login);
    cstmt.registerOutParameter(2, Types.REF);
    cstmt.execute();
    ResultSet rs = (ResultSet)cstmt.getObject(2);

    while (rs.next()) {
        System.out.println(rs.getString(1));
    }
} catch (Exception e) {
    System.err.println(e);
    e.printStackTrace();
}

However, I'm getting the following error:

java.sql.SQLException: ORA-03115: unsupported network datatype or representation

Jacob
  • 14,463
  • 65
  • 207
  • 320
Cup of Java
  • 1,769
  • 2
  • 21
  • 34

1 Answers1

3

First, getCursor method should be used for SYS_REFCURSOR instead of getObject

Second, prepareCall should have BEGIN and END

Code snippet

try {
    CallableStatement cstmt = con.prepareCall("BEGIN proc_search(?, ?); END;");
    cstmt.setString(1, login);
    cstmt.registerOutParameter(2, OracleTypes.CURSOR); 
    cstmt.execute();
    ResultSet rs = ((OracleCallableStatement)cstmt).getCursor(2);

    while (rs.next()) {
        System.out.println(rs.getString("name"));
    }
} catch (Exception e) {
    System.err.println(e);
    e.printStackTrace();
}

As a side note, it is imperative to have a finally block to close Connection, CallableStatement, ResultSet etc.

finally {
    try {
        if (con != null)
            con.close();

        if (cstmt!= null)
            cstmt.close();

        if (rs!= null)
            rs.close();

    } catch (SQLException sqlexc) {
        sqlexc.printStackTrace();
    }
}

Update 1

Using CallableStatement

    Connection conn = null;
    CallableStatement callableStatement = null;
    ResultSet rs = null;

    try {
        conn = getconn();
        callableStatement = conn.prepareCall("{call proc_search(?, ?)}");    
        callableStatement.setString(1, login);
        callableStatement.registerOutParameter(2, OracleTypes.CURSOR);

        callableStatement.executeUpdate();    

        rs = (ResultSet) callableStatement.getObject(2);    
        while (rs.next()) {
            String userid = rs.getString("name");
        }

    } catch (SQLException e) {

        System.out.println(e.getMessage());
        e.printStackTrace();

    } finally {

        if (rs != null) {
            rs.close();
        }

        if (callableStatement != null) {
            callableStatement.close();
        }

        if (conn != null) {
            conn.close();
        }

    }

    }
Jacob
  • 14,463
  • 65
  • 207
  • 320
  • I noticed you are using the Oracle jdbc package for the type and ResultSetCursor, is this necessary to use this package? – Cup of Java Nov 29 '18 at 14:54
  • I was planning on strictly using the built in java SQL library – Cup of Java Nov 29 '18 at 15:15
  • `OracleTypes.CURSOR` is also part of the Oracle package, what would be the equivalent generic type? Would it be `-10` as described [here](https://docs.oracle.com/cd/E16338_01/appdev.112/e13995/constant-values.html#oracle_jdbc_OracleTypes_CURSOR)? – Cup of Java Nov 29 '18 at 15:16
  • 1
    @CupofJava Yes, precisely. If I remember correctly, I too had issues with the return type in JDBC and subsequently always used the Oracle packages and methods. Have a look at [this](https://stackoverflow.com/questions/445455/using-oracle-ref-cursor-in-java-without-oracle-dependency) – Jacob Nov 29 '18 at 15:39