maximum open cursors exceeded exception in java and oracle - java

I having problem with my code:
ERROR: ORA-01000: maximum open cursor exceeded. This code is called from multiple threads.
Q. is oracle cursors are differen than JDBC cursor(resultset)?
public static void viewTable(Connection con, String TBName)
throws SQLException {
Statement stmt = null;
String query = "select *from " + TBName;
try {
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String studentName = rs.getString("STD_NAME");
System.out.println(studentName + "\t");
}
} catch (SQLException e ) {
e.printStackTrace();
} finally {
if (stmt != null) { stmt.close(); }
}
}

Use try-with-resources to ensure that both statement and result set are closed.
String query = "select STD_NAME from " + TBName;
try (Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query)) {
while (rs.next()) {
String studentName = rs.getString("STD_NAME");
System.out.println(studentName + "\t");
}
} // Closes rs and stmt even with exceptions.

You should always close the ResultSet and the Statement. As you said, your code is accessed by many thread so a lot of Resultset will be open and never
closed.
Put the ResultSet variable out of the try catch block and close it in a finally, beside the Statement closing.

Related

Avoiding try-catch-finally hell

let say I have simple connection and select from database. Sadness part of this code is that almost let say 40-50% is try-catch boilerplate code. How can I deal with it?
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
try {
connection = DriverManager.getConnection(
"jdbc:mysql://localhost/test",
"root",
"root"
);
statement = connection.createStatement();
String sql = "SELECT id, name from user";
ResultSet rs = statement.executeQuery(sql);
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.print("ID: " + id);
System.out.print(", name: " + name);
System.out.println();
}
rs.close();
} catch (Exception se) {
se.printStackTrace();
}
finally {
try {
if (statement != null)
statement.close();
} catch (SQLException ignored) {
}
try {
if (connection != null)
connection.close();
} catch (SQLException se) {
se.printStackTrace();
}
}
}
The way to avoid try-catch-finally hell is to use try-with-resources. It was added to the Java language in Java 7. See https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html for a more detailed explanation of this Java language feature.
Here's what your code looks like with try-with-resources
public static void main(String[] args) throws Exception /* bad idea */ {
String sql = "SELECT id, name from user";
try (Connection connection = DriverManager.getConnection(
"jdbc:mysql://localhost/test",
"root",
"root");
Statement statement = connection.createStatement();
ResultSet rs = statement.executeQuery(sql))
{
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.print("ID: " + id);
System.out.print(", name: " + name);
System.out.println();
}
}
}
Note that the try-with-resources will automatically close each of the declared resources (connection, statement and rs) in the reverse order that they were declared, and will deal appropriately with any exceptions that may arise during that. So we don't need any explicit close() calls.
If this was production code, we should NOT declare main as throwing exceptions. We should be dealing with the exceptions properly; i.e. logging them and/or producing a user friendly error message. I'm just taking a shortcut here ... because that's a side-bar to your original question.
You can make your code cleaner with try-with-resources, like that-
try(Connection connection = DriverManager.getConnection(
"jdbc:mysql://localhost/test",
"root",
"root"
);Statement statement = connection.createStatement()) {
String sql = "SELECT id, name from user";
ResultSet rs = statement.executeQuery(sql);
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
System.out.print("ID: " + id);
System.out.print(", name: " + name);
System.out.println();
}
rs.close();
} catch (Exception se) {
se.printStackTrace();
}
It'll handle closing resources. For details go to Oracle Docs
DataSource
Set up a DataSource object with all your connection details such as username and password. Your JDBC driver likely comes with a simple implementation.
SomeDataSourceImplementation ds = new SomeDataSourceImplementation() ;
ds.setUserName( "Scott" ) ;
ds.setPassword( "Tiger" ) ;
…
DataSource dataSource = ds ;
Try-with-resources syntax
The try-with-resources syntax was added years ago to help simplify such code. See Tutorial by Oracle.
If an exception is thrown, the AutoCloseable objects are closed in the reverse order in which they were listed.
String sql = "SELECT id, name from user";
try (
Connection conn = dataSource.getConnection() ;
Statement statement = conn.createStatement() ;
ResultSet rs = statement.executeQuery(sql) ;
) {
while ( rs.next() ) {
int id = rs.getInt( "id" ) ;
String name = rs.getString( "name" ) ;
System.out.print( "ID: " + id );
System.out.print( ", name: " + name ) ;
System.out.println();
}
} catch ( SQLException e ) {
e.printStackTrace();
}

java oracle jdbc resultset empty but record is available in the table

I'm running java 1.8 connecting to oracle 12c using ojdbc7.jar for jdbc connection.
This is the code that execute to retrieve the data
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection("jdbc:oracle:thin:#" +
ipAddress + ":1521:" + dbname,userName,password);
Statement stmt=con.createStatement();
String query = "select * from table_name";
ResultSet rs = stmt.getResultSet();
while (rs.next()) {
System.out.println(rs.getString(1));
}
but the code is not entering the while loop.
When i try exeuction the same query in DB, I could see the table has 10 entries.
Does anyone know what could be the reason?
try{
Class.forName("oracle.jdbc.driver.OracleDriver");
con=DriverManager.getConnection("jdbc:oracle:thin:#" +
ipAddress + ":1521:" + dbname,userName,password);
Statement stmt = con.createStatement();
String query = "select * from table_name";
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
System.out.println(rs.getString(1));
}
} catch (SQLException e ) {
} finally {
if (stmt != null) { stmt.close(); }
}

how do i properly close cursor in loop body because i m getting ERROR: java.sql.SQLException: - ORA-01000: maximum open cursors exceeded

I have been encountered with ORA-01000 SQL exception since following code fetches more than thousand records, so in this regard i would like to know that how do i close ResultSet objects appropriately in loop body so that i may get rid of this exception. Please help me out ... it would b really appreciated ...
Note:-Even though I have opened 2000 cursors in Oracle database.
try
{
String usercode = session.get("usercode").toString();
Date dor = null;
Date eff_date =null;
String emp_category_code = "";
String emp_id = "";
String pay_com = "";
double new_da = 0;
double old_da =0;
int caseCount =0;
con = DBConnect.makeconnect();
con.setAutoCommit(false);
String div_name = session.get("division").toString();
PreparedStatement ps = con.prepareStatement("select emp_id ,category,pay_comm,da as old_da,nvl(pm.EMP_DOR,pm.EMP_DOD) as dor from ABC pm where pm.DIV_NM = ? and sent_to_trea= '1'");
ps.setString(1,div_name);
ResultSet rs = ps.executeQuery();
while(rs.next())
{
emp_id = rs.getString("emp_id");
emp_category_code = rs.getString("category");
pay_com = rs.getString("pay_comm");
dor = rs.getDate("dor");
old_da = rs.getDouble("old_da");
ps = con.prepareStatement("select eff_date,per_amount from XYZ where cat_code=? and relief='DA' and eff_date=(select max(EFF_DATE) from XYZ where PAY_COM=? and cat_code=?) and pay_com=?");
ps.setString(1, emp_category_code);
ps.setString(2, pay_com);
ps.setString(3, emp_category_code);
ps.setString(4, pay_com);
ResultSet rst = ps.executeQuery();
if(rst.next())
{
eff_date = rst.getDate("eff_date");
new_da = rst.getDouble("per_amount");
}
ps = con.prepareStatement("select retirement_gratuity from CAL where emp_id = ?");
ps.setString(1,emp_id);
rst = ps.executeQuery();
if(rst.next())
{
double ret_grat = rst.getDouble("retirement_gratuity");
if(ret_grat >=1000000)
{
continue;
}
}
if(dor.compareTo(eff_date)>0)
{
if(new_da >old_da)
{
ps = con.prepareStatement("select emp_id from AFFECTET where emp_id = ?");
ps.setString(1,emp_id);
rst = ps.executeQuery();
if(!rst.next())
{
ps = con.prepareStatement("insert into upops.AFFECTED (EMP_ID,PREVIOUS_DA,NEW_DA,PREV_GRATUITY,NEW_GRATUITY,REVISION_NO,DONE,EFF_DATE,PAY_COMM,CATEGORY) (select pm.emp_id,pm.da," + new_da + ",c.RETIREMENT_GRATUITY,0,0,'N',to_date('"+eff_date+"','yyyy-MM-dd'),pm.pay_comm,pm.category from upops.pensioner_mast pm ,upops.calculation c where c.emp_id=pm.emp_id and pm.emp_id = '"+emp_id+"')");
int executeUpdate = ps.executeUpdate();
if (executeUpdate > 0) {
ret = CheckUtils.fileMovement(emp_id,usercode , "33", con);
if (ret.equals("SUCCESS")) {
caseCount++;
}
}
}
}
}
else
{
continue;
}
rst.close();
}
ret = "SUCCESS";
if(ret.equals("SUCCESS"))
{
con.commit();
}
}
catch(Exception ex)
{
ex.printStackTrace();;
}
finally
{
try
{
con.close();
}
catch(Exception ex){}
}
If you have to use the Java 7 and above, I prefer you to use try with resources which was introduced in Java 7 new features.
Try-with-resources in Java 7 is a new exception handling mechanism that makes it easier to correctly close resources that are used within a try-catch block.
As to your code:
finally
{
try
{
con.close();
}
catch(Exception ex){}
}
Do you notice that ugly double try?
But, if you used the try with resources , close() is automatically called, if it throws an Exception or not, it will be supressed (as specified in the Java Language Specification 14.20.3) . Same happens for your Database connection and resources case.
Eg.: (JDBC with try with resources)
try (Connection con = DriverManager.getConnection(yourConnectionURL);
PreparedStatement ps = createPreparedStatement(con, userId);
ResultSet rs = ps.executeQuery()) {
// process the resultset here, all resources will be cleaned up
} catch (SQLException e) {
e.printStackTrace();
}
private PreparedStatement createPreparedStatement(Connection con, int userId) throws SQLException {
String sql = "SELECT id, username FROM users WHERE id = ?";
PreparedStatement ps = con.prepareStatement(sql);
ps.setInt(1, userId);
return ps;
}

Error on running multiple select query apache derby

I am not able to run code below with multiple select query. I am able to run queries below individually but I want to run all together and store their results in ArrayList. Error I get is java.sql.SQLException: ResultSet not open. Operation 'next' not permitted. Verify that autocommit is off.
Any advice? or is there a better way to do this? Thanks
public ArrayList<String> getTotalCountBasicQueries() {
ArrayList<String> totalCount = new ArrayList();
Statement stmt = null;
stmt = conn.createStatement();
conn.setAutoCommit(false);
try {
String q1 = "select count query";
String q2 = "select count query2";
String q3 = "select count query3 ";
ResultSet rs = stmt.executeQuery(q1);
ResultSet rs2 = stmt.executeQuery(q2);
ResultSet rs3 = stmt.executeQuery(q3);
while (rs.next()) {
totalBasicCount.add(rs.getString(1));
}
while (rs2.next()) {
totalCount.add(rs2.getString(1));
}
while (rs3.next()) {
totalCount.add(rs3.getString(1));
}
rs.close();
rs2.close();
rs3.close();
stmt.close();
} catch (Throwable e) {
System.out.println("Table fetch failed or result data failed");
} finally {
if (stmt != null) {
try {
stmt.close();
System.out.println("Could not close query");
} catch (SQLException ex) {
System.out.println("Could not close query");
}
}
return totalBasicCount;
}
}
}
See the javadoc for ResultSet :
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.
you can't have multiple resultset open for a unique statement, per spec. however, some jdbc driver allow this
try :
ResultSet rs = stmt.executeQuery(q1);
while (rs.next()) {
totalBasicCount.add(rs.getString(1));
}
ResultSet rs2 = stmt.executeQuery(q2);
while (rs2.next()) {
totalCount.add(rs2.getString(1));
}
ResultSet rs3 = stmt.executeQuery(q3);
while (rs3.next()) {
totalCount.add(rs3.getString(1));
}

could not fetch all data from database in resultset

i am fetching all data from database and stored the resultset to a list. but could not fetch all data. i want to store the data in a dropdownlist. My code is bellow.
public static void updateChallan(){
ChallanNumber pd=null;
int i=0;
String customerName="";
List<ChallanNumber> challanList= new ArrayList<ChallanNumber>();
Connection con = DB.getConnection();
try
{
String st="select CHALLAN_NUMBER,CUSTOMER_CODE,CHALLAN_DATE from DELIVERY_CHALLAN_DETAILS order by CHALLAN_NUMBER";
Statement stmt=con.createStatement();
ResultSet rs=stmt.executeQuery(st);
while(rs.next())
{
String stCustName="select CUSTOMER_NAME from CUSTOMER_DETAILS where CUSTOMER_CODE='"+rs.getString(2)+"'";
Statement stmtCustName=con.createStatement();
ResultSet rsCustName=stmtCustName.executeQuery(stCustName);
while(rsCustName.next()){
customerName=rsCustName.getString(1);
}
customerName=rsCustName.getString(1);
//System.out.println(customerName +" "+i);
pd=new ChallanNumber(rs.getString(1),customerName,rs.getString(3));
challanList.add(i,pd);
i++;
}
}
catch(Exception e)
{
//e.printStackTrace();
}
render(challanList);
}
Dropdownlish code is in bellow.
<select name="challanNumber" id="challanNumber">
<option value="selected" selected="selected">ChallanNumber-CustomerCode- Date</option>
#{list challanList, as:'cl'}
<option value="${cl.challanNumber}">${cl.challanNumber}(${cl.customercode}-${cl.challanDate})</option>
#{/list}
</select>
The problem is that you are not closing the Connection and ResultSet when you get an exception. And so the database has exhausted all open cursors.
You need to close everything you open, it means statement, resultsets. You do that in the finally part of your try/catch to ensure things are correctly closed.
When you close a statement, the resultset linked to that statement is closed too.
public static void updateChallan() throws Exception {
ChallanNumber pd = null;
int i=0;
String customerName = "";
List<ChallanNumber> challanList= new ArrayList<ChallanNumber>();
Connection con = DB.getConnection();
Statement stmt = null;
try {
String st = "select CHALLAN_NUMBER,CUSTOMER_CODE,CHALLAN_DATE from DELIVERY_CHALLAN_DETAILS order by CHALLAN_NUMBER";
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(st);
while (rs.next()) {
String stCustName = "select CUSTOMER_NAME from CUSTOMER_DETAILS where CUSTOMER_CODE='" + rs.getString(2) + "'";
Statement stmtCustName = con.createStatement();
try {
ResultSet rsCustName = stmtCustName.executeQuery(stCustName);
while (rsCustName.next()){
customerName = rsCustName.getString(1);
}
} finally {
if (stmtCustName != null)
stmtCustName.close();
}
customerName = rsCustName.getString(1);
//System.out.println(customerName +" "+i);
pd = new ChallanNumber(rs.getString(1), customerName, rs.getString(3));
challanList.add(i, pd);
i++;
}
} catch(Exception e) {
e.printStackTrace();
} finally {
if (stmt != null)
stmt.close();
}
render(challanList);
}
Besides, you should read the docs of PlayFramework (here for Play2) there are database stuff to avoid using ResultSets and Statements directly, dealing with higher structures like domain objects, the framework will do the rest for you.

Categories