It is possible to Use two query with in single ResultSet
A result set corresponds to a single SQL query. However your "single" query could use UNION to effectively combine more than one query.
No you should not do this.
For example
ResultSet rs = null;
Statement stmt1 = con.createStatement("Query1");
Statement stmt2 = con.createStatement("Query2");
rs = stmt1.executeQuery();
while(rs.next()){
}
//Here result set should be closed before assigning new result set to "rs" variable like
stmt1.close();
rs.close();
rs = stmt2.executeQuery();
You should close old result set before using it again. If you don't close the old resultset object then it will be in memory and never be garbage collected.
If you close the DB connection object in this case(without closing resultset properly) then connection object is not garbage collected(not retuned to pool) as connection have reference(i.e. unclosed resultset).
Related
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?
I am wondering, how do I close an executeUpdate statement in JAVA(JDBC)?
For example:
String sql = "UPDATE. .. . .. Whatever...";
ResultSet rs = stmt.executeQuery(sql);
rs.close();
But I couldn't do this to update. So I googled and found out that I need to use executeUpdate but how do I close the statement after?
String sql = "UPDATE. .. . .. Whatever...";
int rs = stmt.executeUpdate(sql);
rs.close(); ??? <------
You don't close the executeUpdate, you close the Statement:
rs.close(); // Closes the ResultSet
stmt.close(); // Closes the Statement
Usually best to do that with a try-with-resources statement:
String sql = "UPDATE. .. . .. Whatever...";
try (
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
) {
// Process results
}
try-with-resources will close both the Statement and the ResultSet for you. It was added in Java 7 (in 2011).
Side note: You've shown that you're using Statement and calling executeUpdate(String). That's fine as long as there's no externally-sourced information in the SQL (nothing you've received from user input or another system, etc.). In the more common case, though, you'd want to use a PreparedStatement, call setXyz to set parameters, and then call executeUpdate() (the zero-args version). This habit keeps you safe from SQL injection. More explanation and examples on this useful site: http://bobby-tables.com/.
Most of the times when you are updating a table you don't get a ResultSet as the result, So no need to close the ResultSet.
Just close the Statement.
I am new to JDBC and was a bit confused about the syntax. Say I wanted to create multiples queries ( or views in SQL) and refer to a view to make the subsequent queries, how do I do that with prepared statements?
For example:
PreparedStatement first = conn.PreparedStatement("SELECT * FROM clients);
first.execute()
Question Now can I pass the 'PreparedStatement' reference 'first' in the query I am about to create below?
PreparedStatement second = conn.PreparedStatement("SELECT * FROM first WHERE age > 10);
The easiest pattern for JDBC is:
try (PreparedStatement first = conn.prepareStatement(
"SELECT * FROM clients WHERE age BETWEEN ? AND ?")) {
first.setInt(1, 80);
first.setInt(2, 140);
try (ResultSet rs = first.executeQuery()) {
while (rs.next()) {
int age = rs.getInt("age");
...
}
}
}
This syntax: try-with-resources closes first and rs, even if you return or an exception is thrown.
And the statements: first and second are entirely independent.
One does not need to keep the prepared statements open for the entire database session.
The execution is best triggered by executeQuery for SELECT and executeUpdate for UPDATE/INSERT where no ResultSet is yielded.
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
When I execute the following code, I get an exception. I think it is because I'm preparing in new statement with he same connection object. How should I rewrite this so that I can create a prepared statement AND get to use rs2? Do I have to create a new connection object even if the connection is to the same DB?
try
{
//Get some stuff
String name = "";
String sql = "SELECT `name` FROM `user` WHERE `id` = " + userId + " LIMIT 1;";
ResultSet rs = statement.executeQuery(sql);
if(rs.next())
{
name = rs.getString("name");
}
String sql2 = "SELECT `id` FROM `profiles` WHERE `id` =" + profId + ";";
ResultSet rs2 = statement.executeQuery(sql2);
String updateSql = "INSERT INTO `blah`............";
PreparedStatement pst = (PreparedStatement)connection.prepareStatement(updateSql);
while(rs2.next())
{
int id = rs2.getInt("id");
int stuff = getStuff(id);
pst.setInt(1, stuff);
pst.addBatch();
}
pst.executeBatch();
}
catch (Exception e)
{
e.printStackTrace();
}
private int getStuff(int id)
{
try
{
String sql = "SELECT ......;";
ResultSet rs = statement.executeQuery(sql);
if(rs.next())
{
return rs.getInt("something");
}
return -1;
}//code continues
The problem is with the way you fetch data in getStuff(). Each time you visit getStuff() you obtain a fresh ResultSet but you don't close it.
This violates the expectation of the Statement class (see here - http://docs.oracle.com/javase/7/docs/api/java/sql/Statement.html):
By default, only one ResultSet object per Statement object can be open at the same time. Therefore, if the reading of one ResultSet object is interleaved with the reading of another, each must have been generated by different Statement objects. All execution methods in the Statement interface implicitly close a statment's current ResultSet object if an open one exists.
What makes things even worse is the rs from the calling code. It is also derived off-of the statement field but it is not closed.
Bottom line: you have several ResultSet pertaining to the same Statement object concurrently opened.
A ResultSet object is automatically
closed when the Statement object that
generated it is closed, re-executed,
or used to retrieve the next result
from a sequence of multiple results.
I guess after while(rs2.next()) you are trying to access something from rs1. But it's already closed since you reexecuted statement to get rs2 from it. Since you didn't close it, I beleive it's used again below.