In a recent project i need to write a very complex query that,depending on input parameters, have to compose itself. SELECT, FROM, WHERE and ORDER BY clauses were all builded dinamically. For this reason i chose to write a Stored Procedure that achieved this goal.
This one,basically, build the query choosing between a lot of conditions given by input parameters.
At the end of computing job, it open a cursor with the builded query and return it.
The question that this post try to answers is “How can i use a Cursor returned by a PL/SQL Stored Procedure in Java?”
The first step is to declare in PL/SQL a REF CURSOR Type.
I show you a small example of a sub-program that use a REF CURSOR Type
CREATE OR REPLACE
PACKAGE BODY TEST_CURSOR AS
TYPE REF_CUR_TYPE IS REF CURSOR;
PROCEDURE storeProcedureTest(
INPUT_NUM IN NUMBER,
REF_CUR_INSTANCE OUT REF_CUR_TYPE
)
IS
sqlString VARCHAR(100);
BEGIN
sqlString := 'SELECT * FROM';
IF INPUT_NUM=1 THEN
sqlString := sqlString || ' table1';
ELSE
sqlString := sqlString || ' table2';
ENDIF;
OPEN REF_CUR_INSTANCE FOR sqlString;
END storeProcedureTest;
In this very basically stored procedure you have INPUT_NUM that specify on which table you will execute the query. This is a little example that shows a dynamically builded query.
At the TYPE DECLARATION section i define a REF CURSOR type. This say to Oracle that each REF_CUR_TYPE variable is a pointer to a CURSOR.
In the declaration i could make it strongly typed, explicitly defining which kind of rowtype the CURSOR have to return.
TYPE REF_CUR_TYPE IS REF CURSOR RETURN CURSOR_TABLE_TEST%ROWTYPE
At the end Stored Procedure opens REF_CUR_INSTANCE with the builded query. Explicitly note that i DON’T close CURSOR because i want to visit it on Java.
On Java i have to call stored procedure with CallableStatement, registering output Cursor variable. An Oracle Cursor is mapped in Java with java.sql.ResultSet class.
Connection con = null;
CallableStatement callableStmt = null;
ResultSet rs = null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection(
"jdbc:oracle:thin:@address:1521:database_name",
"username",
"password");
callableStmt = con.prepareCall("{ call TEST_CURSOR.storeProcedureTest(?,?) }");
// set the INPUT_NUM parameter
callableStmt.setInt(1, 1);
// register the type of the out parameter for CURSOR
callableStmt.registerOutParameter(2, OracleTypes.CURSOR);
//execute stored procedure
callableStmt.execute()
//get cursor output
rs = callableStmt.getObject(2);
while (rs.next){
//do something useful on cursor
}
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
} catch (SQLException ex) {
ex.printStackTrace();
} finally {
try {
rs.close();
callableStmt.close();
con.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}