I'm having a problem with Resultset during while loop. It's giving me an error java.sql.SQLException: Operation not allowed after ResultSet closed and I can't figure this out. Can anyone help me out? Thanks!
public static void CandidatesPartyList_JComboBox() {
try {
conn1 = VotingSystem.con();
ps = conn1.prepareStatement("SELECT * FROM partylist WHERE p_status = 'Active' ORDER BY p_name ASC");
rs = ps.executeQuery();
candidates_filter_partylist.removeAllItems();
candidates_filter_partylist.addItem("- Select PartyList -");
while (rs.next()) { **<< The problem is coming from here**
candidates_filter_partylist.addItem(rs.getString("p_name"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (Exception e) {
e.printStackTrace();
}
}
if (conn1 != null) {
try {
conn1.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
You've got static variables named conn1, ps, and rs. Static means there is only one variable for the entire virtual machine.
Clearly then, CandidatesPartyList_JComboBox is called twice by different threads and thus the variables are overwritten.
The solution is: None of those things should be fields. They should be local variables, and you should be using try-with-resources, which makes this code less than half the size and fixes the problem. Let's also fix the bad error handling ('print the stack trace' is not handling things, so never write that and update your IDE templates).
public static void CandidatesPartyList_JComboBox() {
try (Connection c = VotingSystem.con();
PreparedStatement ps = c.prepareStatement("SELECT * FROM partylist WHERE p_status = 'Active' ORDER BY p_name ASC");
ResultSet rs = ps.executeQuery()) {
candidates_filter_partylist.removeAllItems();
candidates_filter_partylist.addItem("- Select PartyList -");
while (rs.next()) {
candidates_filter_partylist.addItem(rs.getString("p_name"));
}
} catch (SQLException e) {
throw new RuntimeException("Unhandled", e);
}
}
Related
I try to insert a row to the database, but it doesn't appear in the table after running:
This is the main class:
public class Tester {
public static void main(String[] args) {
CouponsDbDao coupDbDao = new CouponsDbDao();
Coupon coupon = new Coupon(1, 0, Category.Food, null, null, null, null, 25, 0, null);
coupDbDao.addCoupon(coupon);
}
}
And this is the method:
public class CouponsDbDao {
public void addCoupon(Coupon coupon) {
try {
Connection connection = JdbcUtils.getConnection();
String sqlStatement = "insert into coupons (COMPANY_ID,CATEGORY_ID,TITLE,DESCRIPTION,START_DATE,END_DATE,AMOUNT,PRICE,IMAGE) values(?,?,?,?,?,?,?,?,?)";
PreparedStatement statement = connection.prepareStatement(sqlStatement);
statement.setInt(1, coupon.getCompanyId());
statement.setObject(2, coupon.getCategory());
statement.setString(3, coupon.getTitle());
statement.setString(4, coupon.getDescription());
statement.setDate(5, coupon.getStartDate());
statement.setDate(6, coupon.getEndDate());
statement.setInt(7, coupon.getAmount());
statement.setDouble(8, coupon.getPrice());
statement.setString(9, coupon.getImage());
} catch (Exception e) {
e.printStackTrace();
}
}
You need to execute the statement after setting values. Additionally, you need to close the connection created, the preparedstatement etc in a finally block.
public class CouponsDbDao {
Connection connection = null;
PreparedStatement statement = null;
public void addCoupon(Coupon coupon) {
try {
connection= JdbcUtils.getConnection();
String sqlStatement = "insert into coupons (COMPANY_ID,CATEGORY_ID,TITLE,DESCRIPTION,START_DATE,END_DATE,AMOUNT,PRICE,IMAGE) values(?,?,?,?,?,?,?,?,?)";
statement = connection.prepareStatement(sqlStatement);
statement.setInt(1, coupon.getCompanyId());
statement.setObject(2, coupon.getCategory());
statement.setString(3, coupon.getTitle());
statement.setString(4, coupon.getDescription());
statement.setDate(5, coupon.getStartDate());
statement.setDate(6, coupon.getEndDate());
statement.setInt(7, coupon.getAmount());
statement.setDouble(8, coupon.getPrice());
statement.setString(9, coupon.getImage());
statement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
finally{
if (statement != null) {
try {
statement.close();
} catch (SQLException e) { /* print here */}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) { /* print here */}
}
}
}
As told by others you need to call executeUpdate to really perform the query:
Executes the SQL statement in this PreparedStatement object, which must be an SQL Data Manipulation Language (DML) statement, such as INSERT, UPDATE or DELETE
I suggest you also to use the try with resources:
The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
This has been introduced in java 7 and let you eliminate the finally boiler plate code as follow:
// ORIGINAL CODE
Connection connection = ...
try {
connection = JdbcUtils.getConnection();
...
statement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (statement != null) {
try {
statement.close();
} catch (SQLException e) { /* print here */}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) { /* print here */}
}
}
becomes:
// USING try with resources
try (Connection connection = JdbcUtils.getConnection()) {
...
statement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} // NO need of the finally block because connection is AutoCloseable
You need to execute update for statement, like:
statement.executeUpdate();
I'm trying to figure out how to rollback commits from multiple methods. I want to do something like the following (editing for brevity)
public void testMultipleMethodRollback() throws DatabaseException {
Connection conn = connect();
fakeMethodRollback1();
fakeMethodRollback2();
try {
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
}
and currently all my methods are formatted like this
public void fakeMethodRollback1() throws DatabaseException {
Connection con = connect();
PreparedStatement ps = null;
ResultSet rs = null;
// insert some queries
try {
String query = "some query";
ps = conn.prepareStatement(query);
ps.executeUpdate(query);
query = "some query";
ps = conn.prepareStatement(query);
ps.executeUpdate(query);
con.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
throw new DatabaseException(e);
} finally {
close(rs, ps, conn);
}
}
because I want to be able to use the other methods independently, how can I do a rollback where if one method fails, the others will roll back? I fear I have my whole class setup wrong or at least wrong enough that this can't be accomplished without major work. I can't change the methods to return a connection, because half of my methods are get methods, which are already returning other data. Any ideas?
I get this exception while truncating all table in a schema.
I truncate 3 schema in my Java code and first method get list of table names from given schema name and second method executes "TRUNCATE TABLE table_name" query.
I confused about my code always succesful while truncating first and third schema. But while executing on second schema I get ORA-01000 error.
My truncate code is
private void truncateTable(Connection conn, String tableName) {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(Utility.TRUNCATE_TABLE + tableName);
ps.executeUpdate();
} catch (SQLException e) {
log.error("SQLException occured while getting table names from schema", e);
} finally {
Utility.free(ps, null, null);
}
}
private List<String> getAllTableNames(Connection conn) {
PreparedStatement ps = null;
ResultSet rs = null;
List<String> list = new ArrayList<String>();
try {
ps = conn.prepareStatement(Utility.SELECT_ALL_TABLE_NAMES);
rs = ps.executeQuery();
while (rs.next()) {
list.add(rs.getString("TABLE_NAME"));
}
} catch (SQLException e) {
log.error("SQLException occured while getting table names from schema", e);
} finally {
Utility.free(ps, rs, null);
}
return list;
}
public static void free(PreparedStatement ps, ResultSet rs, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
log.error("Error occurred while closing ResultSet",e);
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
log.error("Error occurred while closing PreparedStatement",e);
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
log.error("Error occurred while closing Connection",e);
}
}
}
What is the wrong about code or is it about schema configuraiton in Oracle?
How can I solve this?
If are you iterating over the List generated by getAllTableNames and calling truncateTable in a tight loop, your free calls in the finally block might just be delayed and stacking up to an extent that they aren't clearing fast enough for the next iterations - since you only know the finally will be called at some point, not necessarily immediately and before control is returned to the caller.
The schema size would make a difference to that, so it might make sense that a small schema succeeds and a large one fails. If that is what's happening then you should call free inside the try, as well as in the finally:
private void truncateTable(Connection conn, String tableName) {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(Utility.TRUNCATE_TABLE + tableName);
ps.executeUpdate();
Utility.free(ps, null, null);
ps = null;
} catch (SQLException e) {
log.error("SQLException occured while getting table names from schema", e);
} finally {
if (ps != null) {
Utility.free(ps, null, null);
}
}
}
If Utility.free checks whether ps is null then that check in the finally block might be redundant, but without it, free would be called twice if there is no SQLException.
Check out the code and make sure you are closing the cursors after being used. If the problem still persists please set OPEN_CURSORS to some more value.
In my method show below find bug is specifying Fail to cleanup java.sql.Statement on checked Exception
public int updateSecurityCodeHistoryForMessage(String phone, String securityCodeHistoryId, String messageState, String messageId, String parentMessageId)
{
CaptivePortalLogger.appLog.error(MODULE+"Start : updateSecurityCodeHistoryForMessage::"+messageState);
int result=-1;
String query=null;
Connection con = null;
PreparedStatement pstmt =null;
try
{
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : isSecurityCodeUsed) Available Connection : "+ CaptivePortalDBConnection.getNumIdleConnections());
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : isSecurityCodeUsed) Active Connection : "+ CaptivePortalDBConnection.getNumActiveConnections() );
con = CaptivePortalDBConnection.getDataSource().getConnection();
CaptivePortalLogger.appLog.error(MODULE+" Before updateSecurityCodeHistoryForMessage into SendMessageAndReceiveReport: ");
query="UPDATE tblsecuritycodehistory SET messagestate = ?,messageid = ? WHERE securitycodehistoryid = ? AND mobileno = ?";
CaptivePortalLogger.appLog.debug(MODULE + "for updateSecurityCodeHistoryForMessage in SendMessageAndReceiveReport Query : "+ query);
pstmt = con.prepareStatement(query);
pstmt.setString(1,messageState); //<b>line 556</b>
pstmt.setString(2,messageId);
pstmt.setString(3,securityCodeHistoryId);
pstmt.setString(4,phone);
result = pstmt.executeUpdate();
CaptivePortalLogger.appLog.error(MODULE+" After updateSecurityCodeHistoryForMessage into SendMessageAndReceiveReport: result::"+result);
}
catch (Exception e) {
result = -1;
CaptivePortalLogger.traceLog.debug("Got an exception while updateSecurityCodeHistoryForMessage in SendMessageAndReceiveReport: ",e);
}
finally
{
CaptivePortalLogger.appLog.debug(MODULE+"Finally Start");
try
{
if(pstmt!=null)
pstmt.close();
if(con !=null)
con.close();
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : updateSecurityCodeHistoryForMessage) Closing connections done ....");
}
catch(Exception e)
{
CaptivePortalLogger.traceLog.debug("Error in closing sqlReader.",e);
}
}
CaptivePortalLogger.appLog.error(MODULE+"End : updateSecurityCodeHistoryForMessage");
return result;
}
I find lots of links on stack but none of them able to solve my problem(may be i m not able to understand them properly). Any help will be appreciated.
Thanks in Advance..........
After updaing my finally block with a solution specfied by #Mark problem persists
finally
{
CaptivePortalLogger.appLog.debug(MODULE+"Finally Start");
try {
if(pstmt!=null)
pstmt.close();
} catch (Exception ex) {
// Log, ignore, etc
}
try {
if(con !=null)
con.close();
} catch (Exception ex) {
// Log, ignore, etc
}
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : updateSecurityCodeHistoryForMessage) Closing connections done ....");
}
After using #Jon suggestion , my problem get resolved. finally resolved code is ::
public int updateSecurityCodeHistoryForMessage(String phone, String securityCodeHistoryId, String messageState, String messageId, String parentMessageId)
{
CaptivePortalLogger.appLog.error(MODULE+"Start : updateSecurityCodeHistoryForMessage::"+messageState);
int result=-1;
String query=null;
Connection con = null;
PreparedStatement pstmt =null;
try
{
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : isSecurityCodeUsed) Available Connection : "+ CaptivePortalDBConnection.getNumIdleConnections());
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : isSecurityCodeUsed) Active Connection : "+ CaptivePortalDBConnection.getNumActiveConnections() );
con = CaptivePortalDBConnection.getDataSource().getConnection();
CaptivePortalLogger.appLog.error(MODULE+" Before updateSecurityCodeHistoryForMessage into SendMessageAndReceiveReport: ");
query="UPDATE tblsecuritycodehistory SET messagestate = ?,messageid = ? WHERE securitycodehistoryid = ? AND mobileno = ?";
CaptivePortalLogger.appLog.debug(MODULE + "for updateSecurityCodeHistoryForMessage in SendMessageAndReceiveReport Query : "+ query);
try
{
pstmt = con.prepareStatement(query);
pstmt.setString(1,messageState);
pstmt.setString(2,messageId);
pstmt.setString(3,securityCodeHistoryId);
pstmt.setString(4,phone);
result = pstmt.executeUpdate();
}
catch(SQLException e1)
{
CaptivePortalLogger.traceLog.debug("Error in closing sqlReader.",e1);
}
finally{
if(pstmt!=null)
pstmt.close();
}
CaptivePortalLogger.appLog.error(MODULE+" After updateSecurityCodeHistoryForMessage into SendMessageAndReceiveReport: result::"+result);
}
catch (SQLException e2) {
result = -1;
CaptivePortalLogger.traceLog.debug("Got an exception while updateSecurityCodeHistoryForMessage in SendMessageAndReceiveReport: ",e2);
}
finally
{
CaptivePortalLogger.appLog.debug(MODULE+"Finally Start");
try
{
if(con !=null)
con.close();
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : updateSecurityCodeHistoryForMessage) Closing connections done ....");
}
catch(SQLException e)
{
CaptivePortalLogger.traceLog.debug("Error in closing sqlReader.",e);
}
}
CaptivePortalLogger.appLog.error(MODULE+"End : updateSecurityCodeHistoryForMessage");
return result;
}
Look at this code:
if(pstmt!=null)
pstmt.close();
if(con !=null)
con.close();
Now consider that pstmt.close() can throw an exception... which means con.close() wouldn't be called.
If you're using Java 7, use a try-with-resources statement instead, but otherwise you should have a separate try/finally block for each resource.
try {
connection = ...;
try {
statement = ...;
} finally {
// Clean up statement
}
} finally {
// Clean up connection
}
I'd also strongly recommend against catching blanket Exception - it's better to catch specific exceptions which you can actually handle, and let other exceptions propagate up the stack. Also, you appear to be using integer values to signal success or failure of your method - that's not idiomatic Java; exceptions are preferred for error handling, in general.
The problem is that if pstmt.close() throws an Exception, then the connection is never closed.
Either do not close the statement in the finally (as drivers are required to close Statement objects if the Connection is closed), or put both in their own try..catch-block. Eg:
finally
{
CaptivePortalLogger.appLog.debug(MODULE+"Finally Start");
try {
if(pstmt!=null)
pstmt.close();
} catch (Exception ex) {
// Log, ignore, etc
}
try {
if(con !=null)
con.close();
} catch (Exception ex) {
// Log, ignore, etc
}
CaptivePortalLogger.sysOut.debug(MODULE + " (Method : updateSecurityCodeHistoryForMessage) Closing connections done ....");
}
Firebug is correct.
You should close all your SQL resources in a finally block, using individually wrapped calls to close methods.
You can do it with a utility class:
package persistence;
public class DatabaseUtils {
// similar methods for ResultSet and Connection
public static void close(Statement s) {
try {
if (s != null) {
s.close();
}
} catch (SQLException e) {
// Log the exception
}
}
}
Call the close method in a finally block in the method that created the resource.
Try to cleanup /close resource in separate try/catch/finally block otherwise if any one throw an exception then rest of will be remain unclosed.
There are many steps involved in executing one SQL statement in Java:
Create connection
Create statement
Execute statement, create resultset
Close resultset
Close statement
Close connection
At each of these steps SQLException can be thrown. If we to handle all exception and release all the resources correctly, the code will will look like this with 4 levels of TRY stacked on the top of each other.
try {
Connection connection = dataSource.getConnection();
try {
PreparedStatement statement = connection.prepareStatement("SELECT 1 FROM myTable");
try {
ResultSet result = statement.executeQuery();
try {
if (result.next()) {
Integer theOne = result.getInt(1);
}
}
finally {
result.close();
}
}
finally {
statement.close();
}
}
finally {
connection.close();
}
}
catch (SQLException e) {
// Handle exception
}
Can you propose a better (shorter) way to execute a statement while still release all the consumed resources?
If you are using Java 7, the try with resources statement will shorten this quite a bit, and make it more maintainable:
try (Connection conn = ds.getConnection(); PreparedStatement ps = conn.prepareStatement(queryString); ResultSet rs = ps.execute()) {
} catch (SQLException e) {
//Log the error somehow
}
Note that closing the connection closes all associated Statements and ResultSets.
Check out Apache Commons DbUtils, and in particular the closeQuietly() method. It will handle the connection/statement/result set closing correctly, including the cases where one or more are null.
An alternative is Spring JdbcTemplate, which abstracts a lot of work away from you, and you handle your database queries in a much more functional fashion. You simply provide a class as a callback to be called on for every row of a ResultSet. It'll handle iteration, exception handling and the correct closing of resources.
I create a utility class with static methods I can call:
package persistence;
// add imports.
public final class DatabaseUtils {
// similar for the others Connection and Statement
public static void close(ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
} catch (Exception e) {
LOGGER.error("Failed to close ResultSet", e);
}
}
}
So your code would be:
Integer theOne = null;
Connection connection = null;
PreparedStatement statment = null;
ResultSet result = null;
try {
connection = dataSource.getConnection();
statement = connection.prepareStatement("SELECT 1 FROM myTable");
result = statement.executeQuery();
while (result.next()) {
theOne = result.getInt(1);
}
} catch (SQLException e) {
// do something
} finally {
DatabaseUtils.close(result);
DatabaseUtils.close(statement);
DatabaseUtils.close(connection);
}
return theOne;
I'd recommend instantiating the Connection outside this method and passing it in. You can handle transactions better that way.
Connection connection = null;
PreparedStatement statement = null;
ResultSet result = null;
try {
connection = dataSource.getConnection();
statement = connection.prepareStatement("SELECT 1 FROM myTable");
result = statement.executeQuery();
if (result.next()) {
Integer theOne = result.getInt(1);
}
}
catch (SQLException e) { /* log error */ }
finally {
if (result != null) try { result.close(); } catch (Exception e) {/*log error or ignore*/}
if (statement != null) try { statement.close(); } catch (Exception e) {/*log error or ignore*/}
if (connection != null) try { connection.close(); } catch (Exception e) {/*log error or ignore*/}
}
Just close the Connection, this releases all resources*. You don't need to close Statement and ResultSet.
*just make sure you don't have any active transactions.
Your code can be shortened and written in this way...
Connection connection = dataSource.getConnection();
PreparedStatement statement = null;
ResultSet result = null;
try {
statement= connection.prepareStatement("SELECT 1 FROM myTable");
result = statement.executeQuery();
if (result.next()) {
Integer theOne = result.getInt(1);
}
} catch (SQLException e) {
// Handle exception
} finally {
if(result != null) result.close();
if(statement != null) statement.close();
if(connection != null) connection.close();
}