Getting a result back from a stored procedure in Java - java

I am having the hardest time calling an Oracle stored procedure from a java runtime environment. The stored procedure that I am calling has 2 parameters 1 in and 1 out. Here is how I call the stored procedure... How do you get the resultSet from an Oracle ref_cursor
ds = (DataSource)initialContext.lookup("JDBC/EPCD13DB");
conn = ds.getConnection();
callableStatement = conn.prepareCall(storedProcCall);
callableStatement.setString(1, input1);
callableStatement.registerOutParameter(2, OracleTypes.CURSOR);
callableStatement.execute();//(ResultSet) callableStatement.getObject(1);
ResultSet rs = callableStatement.getResultSet();
while(rs.next()){
Provider tempProv = new Provider();
tempProv.setResourceId(rs.getLong("res_id"));
tempProv.setFirstName(rs.getString("First_Name"));
tempProv.setLastName(rs.getString("Last_Name"));
tempProv.setMiddleName(rs.getString("Middle_Name"));
ObjList.add(tempProv);
}
rs.close();

You should be able to retrieve the ResultSet with:
ResultSet rSet = (ResultSet)callableStatement.getObject(2);

Does this help you? Seems like you have to call getObject and cast it into a result set before querying on the result set.
Credit:: http://www.mkyong.com/jdbc/jdbc-callablestatement-stored-procedure-cursor-example/

I believe it returns only one output(oracle cursor)
ResultSet rs=(ResultSet) callableStatement.getObject(2);
and then iterate your cursor result set for records inside:
while(rs.next()){
Provider tempProv = new Provider();
tempProv.setResourceId(rs.getLong("res_id"));
tempProv.setFirstName(rs.getString("First_Name"));
tempProv.setLastName(rs.getString("Last_Name"));
tempProv.setMiddleName(rs.getString("Middle_Name"));
ObjList.add(tempProv);
}

In spring framework fetching database cursor results can be easily achieved. It has inbuilt classes like maprow, storedprocedure to serve the purpose. PFB the link
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/jdbc.html#jdbc-simple-jdbc-call-1

Related

DatabaseChangeNotification is not triggering when blob content is updated

When I updated blob in Database, DatabaseChangeNotification has to trigger but it's not happening.
Working fine with normal string/varchar but it's not working with blob.
I am trying as below
OracleConnection conn = connect();
Properties prop = new Properties();
prop.setProperty(OracleConnection.DCN_NOTIFY_ROWIDS,"true");
prop.setProperty(OracleConnection.DCN_QUERY_CHANGE_NOTIFICATION,"true");
DatabaseChangeRegistration dcr = conn.registerDatabaseChangeNotification(prop);
try {
DCNDemoListener list = new DCNDemoListener(this);
dcr.addListener(list);
Statement stmt = conn.createStatement();
((OracleStatement) stmt).setDatabaseChangeRegistration(dcr);
ResultSet rs = stmt.executeQuery("select * from TEST_MODEL");
rs.close();
stmt.close();
stmt = conn.createStatement();
ResultSet rss = stmt.executeQuery("select TESTSUITE_NAME,TESTSUITE_DEFINITION from TESTSUITE_MODELS");
while (rss.next()) {
System.out.println(rss.getString("TESTSUITE_NAME"));
System.out.println(rss.getBlob("TESTSUITE_DEFINITION"));
}
rss.close();
stmt.close();
Can anyone help me in this?
If I am trying to query table which conatian blob column I am getting "ORA-29977: Unsupported column type for query registration in guaranteed mode for blolb" exception
ResultSet rss = stmt.executeQuery("select TESTSUITE_NAME,TESTSUITE_DEFINITION from TESTSUITE_MODELS");
I haven't used database change notification (thanks for the hint, looks quite interesting!), but found the following in the documentation:
To be registered for QRCN in guaranteed mode, a query must conform to the following rules:
Every column that it references is either a NUMBER data type or a VARCHAR2 data type.
The section about QRCN in best effort mode seems not to have this restriction.
Does anybody know how to use the best effort mode from JDBC?

Calling PL/SQL package code in a Java Program

I am trying to call a procedure defined with a PL/SQL package in a Java program.
I am aware one can call stored procedures using connection.prepareCall in Jdbc. But there is very little information out there on how to call a procedure within a package.
I am at a stage in development where i am still considering what db framework to use. Just wondering what are the pros and cons of using JDBC for PLSQL ? For this usecase are there better alternatives to JDBC ?
Follow the simple steps below:
public static final String SOME_NAME = "{call schema_name.org_name_pkg.return_something(?,?)}"; // Change the schema name,packagename,and procedure name.
// Simple JDBC Connection Pooling
// Here I am passing param companyId which is IN param to stored procedure which will return me some value.
Connection conn = null;
CallableStatement stmt = null;
ResultSet rset = null;
try {
conn = DriverManager.getConnection("jdbc:mysql://hostname:port/dbname","username", "password");
stmt = conn.prepareCall(SOME_NAME);//We have declared this at the very top
stmt.setString(1, companyid);//Passing CompanyID here
stmt.registerOutParameter(2, OracleTypes.CURSOR);//Refcursor selects the row based upon query results provided in Package.
stmt.execute();
rset = (ResultSet) stmt.getObject(2);
while (rset.next()) {
String orgId=rset.getString("RPT_ORG_ID");
// When using refcursor easy to get the value just by using Column name
String orgName=rset.getString("RPT_ORG_NAME");
// Some Logic based what do you want to do with the data returned back from query
} catch (Exception e) {
LOGGER.error("Error extracting ", e);
} finally {
DBUtils.cleanUp(conn, stmt, rset);
}
// Clean and close you connection

How to execute a sql stored procedure from Java Hibernate using Session Factory?

I am unable to call my stored procedure from java hibernate using session factory
I have written a sql procedure which takes 5 parameters and return a result set which works fine in MS SQL studio
EXEC SlaGrid #appID=245,#fromYear=2012,#toYear=2013,#fromMon=1,#toMon=12 --- sql
EXEC SlaGrid #applID=:applID,#fromYear=:fromYear,#toYear=:toYear,#fromMon=:fromMon,#toMon=:toMon --hibernate
i am setting the parameters for the above query
String queryString = "EXEC SlaGrid #applID=:applID,#fromYear=:fromYear,#toYear=:toYear,#fromMon=:fromMon,#toMon=:toMon"
Query query = sessionFactory.getCurrentSession().createSQLQuery(queryString);
//set query parameters here
query.list() --- giving sql grammer exception
You can use callable statement on hibernate session.
Connection con = getSessionFactory().getCurrentSession().connection();
/**
* Amend to include your parameters and proc
*/
CallableStatement cs = con.prepareCall( "{ call myprocedure }");
cs.execute();
create a SessionFactory and Open a session then
CallableStatement callableStatement = session.connection().prepareCall("call GetMarketDataCDS(?,?)");
callableStatement.setString(1,"JPM");
callableStatement.registerOutParameter(1, OracleTypes.CURSOR);
callableStatement.execute();
ResultSet resultSet=(ResultSet) callableStatement.getObject(1);
here i am using oracle and my first param is IN Parameter and second is OUT which is nothing but a resultset returning multiple rows.
Then in last line we get the ResultSet with all row and then you can iterate through the rows.
I solved it simply by the following code...Just pass the parameters in CSV.Thanks for the help guys..
String queryString = "SlaGrid 245,2012,2013,1,12"
Query query = sessionFactory.getCurrentSession().createSQLQuery(queryString);
query.list();
Works Perfect :)
Try this
Query query = sessionFactory.getCurrentSession().createSQLQuery(
"CALL SlaGrid(:appID, :fromYear, :toYear, :fromMon, :toMon)")
.setParameter("appID", 245)
.setParameter("fromYear", 2012)
.setParameter("toYear", 2013)
.setParameter("fromMon", 1)
.setParameter("toMon", 12);

Get last insert id with Oracle 11g using JDBC

I'm new to using Oracle so I'm going off what has already been previously answered in this SO question. I just can't seem to get it to work. Here's the statement that I'm using:
declare
lastId number;
begin
INSERT INTO "DB_OWNER"."FOO"
(ID, DEPARTMENT, BUSINESS)
VALUES (FOO_ID_SEQ.NEXTVAL, 'Database Management', 'Oracle')
RETURNING ID INTO lastId;
end;
When I call executeQuery the PreparedStatement that I have made, it inserts everything into the database just fine. However, I cannot seem to figure out how to retrieve the ID. The returned ResultSet object will not work for me. Calling
if(resultSet.next()) ...
yields a nasty SQLException that reads:
Cannot perform fetch on a PLSQL statement: next
How do I get that lastId? Obviously I'm doing it wrong.
make it a function that returns it to you (instead of a procedure). Or, have a procedure with an OUT parameter.
Not sure if this will work, since I've purged all of my computers of anything Oracle, but...
Change your declare to:
declare
lastId OUT number;
Switch your statement from a PreparedStatement to a CallableStatement by using prepareCall() on your connection. Then register the output parameter before your call, and read it after the update:
cstmt.registerOutParameter(1, java.sql.Types.NUMERIC);
cstmt.executeUpdate();
int x = cstmt.getInt(1);
I tried with Oracle driver v11.2.0.3.0 (since there are some bugs in 10.x and 11.1.x, see other blog). Following code works fine:
final String sql = "insert into TABLE(SOME_COL, OTHER_COL) values (?, ?)";
PreparedStatement ps = con.prepareStatement(sql, new String[] {"ID"});
ps.setLong(1, 264);
ps.setLong(2, 1);
int executeUpdate = ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();
if (rs.next() ) {
// The generated id
long id = rs.getLong(1);
System.out.println("executeUpdate: " + executeUpdate + ", id: " + id);
}
When you prepare the statement set the second parameter to RETURN_GENERATED_KEYS. Then you should be able to get a ResultSet off the statement object.
You can use Statement.getGeneratedKeys() to do this. You just need to make sure to tell JDBC what columns you want back using one of the method overloads for that, such as the Connection.prepareStatement overload here:
Connection conn = ...
PreparedStatement pS = conn.prepareStatement(sql, new String[]{"id"});
pS.executeUpdate();
ResultSet rS = pS.getGeneratedKeys();
if (rS.next()) {
long id = rS.getLong("id");
...
}
You don't need to do the RETURNING x INTO stuff with this, just use the basic SQL statement you want.
Are you doing that in a stored procedure ? According to this Oracle document, it won't work with the server-side driver.
The Oracle server-side internal driver does not support
the retrieval of auto-generated keys feature.

What is the equivalent of Oracle’s REF CURSOR in MySQL when using JDBC?

In Oracle I can declare a reference cursor...
TYPE t_spool IS REF CURSOR RETURN spool%ROWTYPE;
...and use it to pass a cursor as the return value...
FUNCTION end_spool
RETURN t_spool
AS
v_spool t_spool;
BEGIN
COMMIT;
OPEN v_spool FOR
SELECT
*
FROM
spool
WHERE
key = g_spool_key
ORDER BY
seq;
RETURN v_spool;
END end_spool;
...and then capture it as a result set using JDBC...
private Connection conn;
private CallableStatement stmt;
private OracleResultSet rset;
[...clip...]
stmt = conn.prepareCall("{ ? = call " + call + "}");
stmt.registerOutParameter(1, OracleTypes.CURSOR);
stmt.execute();
rset = (OracleResultSet)stmt.getObject(1);
What is the equivalent in MySQL?
Mysql has an implicit cursor that you can magically return from a stored procedure if you issue a select.
Here's an example:
CREATE PROCEDURE `TEST`()
MODIFIES SQL DATA
BEGIN
SELECT * FROM test_table;
END;
and in your java code:
String query = "{CALL TEST()}";
CallableStatement cs = con.prepareCall(query,
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet rs = cs.executeQuery();
Googling on cursors in MySQL, it doesn't seem like you can actually return a Cursor from a Proc or Function. Additionally, I found the following in the MySQL JDBC manual:
"MySQL does not support SQL cursors, and the JDBC driver doesn't emulate them, so "setCursorName()" has no effect."
In general, I believe Oracle's implementation here breaks JDBC, and is not used elsewhere (MySQL, MSSQL, etc). You should be returning your results as a select statement and iterating over the JDBC ResultSet, as is standard (and intended) practice when using JDBC.
fill a temporary table in a procedure and just read the temporary table... :)

Categories