I have a try-catch-finally block that looks like so:
ResultSet rs;
PreparedStatement ps;
Connection conn;
try {
for (int i = 0; i < list.size(); i++) {
** execute SQL query **
}
} catch (Exception e) {
throw e;
} finally {
** close result set **
** close prepared statement **
** close connection **
}
I've verified that my ArrayList list had 534 elements in it. The problem is that the finally block to close everything is executing after the first occurrence of my for loop which causes the next occurrence to throw an exception because the connection is now closed.
I've never encountered a situation where the finally block executes before the try block has completed. What could cause this scenario?
Basically, what is happening is that finally is working as expected. The short explanation is that a finally block is executed no matter how the try block terminates.
In your example, and based on what you have said, the most likely scenario is as follows:
the loop body throws some exception,
the exception is caught and rethrown, and
the finally block is then executed.
The finally block will NOT be executed before the try block "terminates", so your theory that the finally block is causing the loop body to fail is not correct.
Reference: http://docs.oracle.com/javase/tutorial/essential/exceptions/finally.html
Without more source I would guess that you are not committing your transaction.
If you switch your connection to not auto-commit and then forget to commit your transaction it may seem like your finally block is executing before your queries when in fact they are merely awaiting committal before executing.
See here for a discussion.
Related
In following two examples, I am 1) closing the database in the finally block and 2) closing it after the try ... catch. Does it make a difference which approach is used? If no, what is the point of finally, as we can release resources without using it?
try{
// initialise a database connection
} catch (Exception e) {
e.printStackTrace();
} finally{
db.close
}
Second
try{
// initialise a database connection
} catch (Exception e) {
e.printStackTrace();
}
db.close
One way to explain why finally is better / necessary is to point out the flaws in this version of the code:
try {
// initialise a database
} catch (Exception e) {
e.printStackTrace();
}
db.close();
The first problem is that if some exception that is a subtype of Error is thrown, then the try ... catch won't catch it. Error is a subtype of Throwable but not of Exception.
You might counter that one should not attempt to recover from an Error exception. That is true in many contexts, but not in others. For example, if this code was executed in a worker thread, a lot of frameworks will try to create a new thread to replace the one that died. That would result in the database handle leaking.
The second problem is that you are catching and squashing exceptions. Indeed, for the code as you have written it, you have to do this for the db.close() at the end to be executed. This might work in your example, but it won't work in general. For instance, what if you need to return something from this code ... or allow the exception to propagate for the caller to deal with.
The third problem is that you are catching Exception so that you can close db.close() in all cases. However, by doing this, you are most likely catching exceptions that should not be caught at this level. For example, if something withing the try block throws an NPE, you should not "squash and recover". Instead, you should allow the exception to propagate.
Note that using finally means that you don't have to worry about leakage in the case of Errors, recovering when you don't want to, or catching more exceptions than you mean to.
Now you can attempt to work around the three problems above without using finally, but it introduces other problems. (For example you could catch and then rethrow Exception with a db.close() in the handler, but then you would typically need to declare the enclosing method as throws Exception!)
Note that calling printStackTrace() like that is not advisable. A better approach is to use a logging framework ... so that the error reporting can be managed via a configuration file.
Finally, the block is a safe point to close the resource as finally block will execute in every situation until the System#exit called. It may happen that catch is also thrown an exception, in that case, your resource will not close if you put outside after catch block.
It seems to me that the question is what is the difference between closing the database connection in the finally block versus after the finally block.
I will assume that the database was opened INSIDE the try block. If the code inside the try block threw an exception and your closed the database only after the finally block, you won't close the database when the exception is handled.
The correct way to do this is to close the database in the finally block. The finally block will run unconditionally, whether an exception was thrown or not.
Consider a little more specific example:
try{
// initialise a database
} catch (SocketException e) {
e.printStackTrace();
} finally{
db.close
}
This will cleanup even if the exception was not a SocketException.
try{
// initialise a database
} catch (SocketException e) {
e.printStackTrace();
}
db.close
This won't. It will just bubble up the exception.
(I chose SocketException randomly. This of course goes as well for other Exceptions, Throwables etc)
Baseline: Using the finally block to perform clean-up fortifies your code against unexpected exceptions and exceptions thrown in your catch-blocks.
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try
{
conn = geting the connection object ( using DriverManager.getConnection() method or using connection pool)
stmt = conn.createStatement ("select ...");
// some other logic here
}
catch (SQLException e)
{
// handling the exceptions
}
finally
{
}
Here my question is while closing the connection object in the following cases what are the problems it will come.
Assume if there is no exception occurred, in try block there it self closing the connection object.
try {
// same above code
stmt.close();
conn.close();
} catch(Exception ex) {
// handling the exceptions
} finally {
}
If some exception is occured so it will goes to catch block, there it self closing the connection object.
try {
// same above code
} catch(Exception ex) {
// handling the exceptions
stmt.close();
conn.close();
} finally {
}
Closing the connection object in finally block.
try {
// same above code
} catch(Exception ex) {
// handling the exceptions
} finally {
stmt.close();
conn.close();
}
Difference between closing the connection object using close() method and closing the pooled connection using close().
Note: Please don't say closing the connection object in finally block is good. I know that one. If i keep the close connection in try block, catch block is there any problems please explain.
It is recommended to close the connection in the finally block because if you have multiple catch blocks (as you should: you should never catch generic Exception) you will not have to re-write the closing statements.
A finally block will always be executed after a try, no matter what happens. So if you get a NullPointerException, or some other exception you didn't handle, with the finally block you will be sure that your resources are closed properly.
But if you are on java 7, I'd suggest to use the try-with-resources block
As database is consuming more resources, it is always recommended to close your connection after your processing is done whether successfully or not.
You said that adding conn.close() in try, this is fine if your query runs without any exception and what if your query has any issues, the connection would not be closed. So it is always recommended to close your connection in finally block which is executed always irrespective of whether exception occurred or not. Also if you try to put the closing statement in catch block and your trying to handle multiple exceptions you will need to repeat your code which is not recommended.
Answer is that 'We must close the connection after using it.' But the actual question is why we must close the connection after using?.
1.) When we create a connection with a remote database server lets say MySQL Server, It also keeps a connection open for you. Due there is a also a limitation/configuration at database server end for number of connection allowed. If we don't close the connection from our end it will remain open and such way after a short while number of allowed connections will be exceeded at database server end and we will not be able to make further connection with that database.
2.) Auto release connections time setting at database server side.
If we don't close connection from our end and we don't execute any query for certain period of time (As I think default time setting in MySql is 28800 sec. means 8 Hrs. Although we can change it.) it will automatically release the connection from server end.
Important! What will happen in that situation when your jdbc Connection object is really released at database server end and you think it is still connected because you never disconnected/closed it and you are trying to executing query on that connection using statement. Really critical.
That's why we must always close the connection and execute statement on connected connection object.
The finally block is always executed, including the following cases:
Normal termination of the try-block.
Exceptional termination of the try-block when exception is handled in some catch.
Exceptional termination when exception is propagated to the caller.
A return statement in the middle of the block:
try {
if(something) return false; // finally is executed here as well
...
} finally { ... }
A break or continue statement if the whole try-catch is inside the loop:
while(condition) {
try {
if(something) continue; // finally is executed here
else if(somethingElse) break; // finally is executed here
...
}
finally {
}
}
Thus no matter how you exit the try block, the finally will be executed and you should not care about checking every possible exiting way. This is really convenient.
finally block always execute :
try{
// code logic
}catch(SQLException ex){
// catch exception
}finally{
if (dbConnection != null){
dbConnection.close();
}
}
What happens if an exception you're not handling gets thrown? (I
hope you're not catching Throwable...)
What happens if you return from inside the try block?
What happens if the catch block throws an exception?
A finally block makes sure that however you exit that block (modulo a few ways of aborting the whole process explicitly), it will get executed. That's important for deterministic cleanup of resources.
Note : Also for preventing application resource leaking we have to close connection anyway..!!
Thanks.!!
You can close connection in try or in catch block, but will tell you why is good to close connection in finally Block
Suppose you have try catch block as below:
try{
stmt1..
stmt2..
conn.close
}
catch(exception e){
}
Now suppose exception is raised by stm1 then your connection will remain open.
Now consider you are closing connection in catch block..what if no exception raised then control will never come in catch block.. here connection is still open.. I hope i am able to clear few of you doubts.
I have been playing around with JDBC drivers. I would like some advice from the experience code masters out there. I was wondering if this is a good way to find if am connected to a database. If it is not, could someone let me know how would they do it?
Connection con = null;
try {
con = DriverManager.getConnection("jdbc:mysql://localhost/"+database+"?+user="+user+"&password="+password);
} catch (SQLException e) {
System.out.println(e.getMessage());
if (con != null) {
System.out.println("hello");
} else {
System.out.println("Not Connected!");
}
}
I would really appreciate all helpful comments. Many thanks in advance.
If the getConnection method returns normally, and does not throw an exception, then a connection to the database has been made. The logic within the catch clause is unrequired, because if an exception is caught a connection was not established.
The returned Connection object must be close()d (as many of the JDBC classes must, such as Statements and ResultSets for example). Assuming Java7, a convenient way to ensure the Connection is closed is using the try-with-resources statement:
try (Connection con = DriverManager.getConnection(...))
{
}
catch (final SQLException e)
{
}
As stated by SnakeDoc in the comments this may be impractical in production systems because establishing a connection to the database is a typically expensive operation.
The JDBC API will perform these checks for you. Whenever you perform a database operation, such as opening a connection, executing a statement, it will check to see if the connection is valid. If not it will throw an exception.
For example, the method Connection.createStatement throws the following:
SQLException - if a database access error occurs or this method is called on a closed connection
All you have to do is some basic exception handling. Surrounding your JDBC calls with try-catch blocks is one way do this. You could also throw the exception and handle it somewhere else.
That's definitely a good way of doing it! If conn can't be initialised it's either your connection string that is wrong or the database is down.
According to JAVA documentation, Connection#commit() can throw SQLException. My question is whether or not a rollback should still be issued in this scenario.
For example:
Connection con = null;
try {
// assume this method returns an opened connection with setAutoCommit(false)
con = createConnection();
// do DB stuff
con.commit();
} catch (SQLException e) {
if (con != null) {
// what if con.commit() failed, is this still necessary,
// will it hurt anything?
con.rollback();
}
} finally {
if (con != null) {
con.close();
}
}
I actually wrapped the con.rollback() call into another method which ignores any exceptions thrown by it, so I think I'm ok here. I just wondered if this was the best way of handling things.
Rollback is important even if commit failed, according to the Java 1.6 JDBC docs:
It is strongly recommended that an application explicitly commits or
rolls back an active transaction prior to calling the close method. If
the close method is called and there is an active transaction, the
results are implementation-defined.
This means that if you do not explicitly invoke rollback, some JDBC implementation might invoke commit before closing the connection.
Another good reason to rollback is as Xepoch suggested and when using a connection pool it is even more important.
When getting a connection from a connection pool, most implementations will execute connection.setAutoCommit(defaultAutoCommit) before giving you the connection and according to the JavaDocs:
If this method is called during a transaction and the auto-commit mode
is changed, the transaction is committed
If the connection.rollback() throws an exception - then it is a tricky one...
I would do explicit rollback just for clean-up purposes. Although changes won't be persisted in db either way, it seems nice to explicitly let database know that you're done here. Just like the way you close connection explicitly, without waiting for Connection object to be garbage-collected.
This is, obviously, not a technical answer and I would also be interested to learn whether there's a practical point in doing so.
"Returns an open connection?" If that connection is shared in a pool (and could be in the future) you don't want another transaction committing your earlier work. I've seen MANY customer/solution cases of plugging in pooled connection driver that comply with JDBC interfaces and Connection.close() can also be used to just return the Connection back to a pool.
Also, better try{}catch{} your rollback() (edit, just read your whole post, but I always like to log an exception on rollback)
The usual way I do this is:
boolean bSuccess = false;
Connection con = null;
try {
// assume this method returns an opened connection with setAutoCommit(false)
con = createConnection();
// do DB stuff
bSuccess = true;
} catch (SQLException e)
{
}
finally
{
try
{
if (con != null)
{
if(bSuccess)
con.commit()
else
con.rollback();
con.close();
}
}
catch(SQLException sqle)
{
log("Log the error here");
// do nothing we tried
}
}
That being said I have never seen a commit or a rollback fail if the queries worked.
If you have pending transactions then most databases have tools to free them. Most app servers will keep retrying the commits and rollbacks until they can connect.
You might want to look at this post: Is it necessary to write ROLLBACK if queries fail?
Say you have the following code:
Connection conn;
try
{
conn = ... // get connection
conn.setAutoCommit(false);
... // Do some modification queries and logic
conn.commit()
} catch(SQLException e)
{
conn.rollback() // Do we need this?
conn.close()
}
In this code, if there is an exception, is it better style to just close the connection (since autocommit is off), or to explicitly roll back and then close the connection? There are no save points.
I feel that it might make sense to add the rollback call because:
1) Someone, in the future, might add save points but forget to add the rollback
2) It improves readability
3) It shouldn't cost anything, right ?
But obviously, none of these is particularly compelling. Any standard practice?
Note: I'm aware of the need to do a repeat try/catch on closing and rollback. I actually have a middleware that abstracts the database access and takes care of that, but I was wondering whether adding it was superfluous.
The normal idiom is the following:
public void executeSomeQuery() throws SQLException {
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
try (PreparedStatement statement = connection.prepareStatement(SOME_SQL)) {
// Fire transactional queries here.
connection.commit();
} catch (SQLException e) {
connection.rollback();
throw e;
}
}
}
Note that Java 7's try-with-resources statement always implicitly calls close() on the resource when the try block finishes, as if it happens in finally.
Calling rollback() is also mandatory when it concerns a pooled connection. Namely, it will reset the transactional state of the connection. The close() of a pooled connection won't do that, only the commit() and rollback() will do that. Not calling rollback() may lead that the next lease of the pooled connection will still have the (successful) queries of the previous transaction in its memory.
See also javadoc of Connection#close() (emphasis not mine):
It is strongly recommended that an application explicitly commits or rolls back an active transaction prior to calling the close method. If the close method is called and there is an active transaction, the results are implementation-defined.
Closing should rollback because it will not commit when the resources are release, but it's good to have your error handling be specific, so if you want to rollback on an exception, do that. Then you can do your cleanup in a finally{} block. The rollback() occurs only on error, in which case your commit() is not successful or was not even reached.
Connection conn = null;
try {
conn = ...
...
conn.commit();
}
catch (SQLException e) {
if (conn != null) {
conn.rollback();
}
}
finally {
if (conn != null) {
conn.close();
}
}