I asked this question (How do I call java.sql.Connection::abort?) and it led me to another question.
With
java.sql.Connection conn = ... ;
What is the difference between
conn.close();
and
conn.abort(...);
?
You use Connection.close() for a normal, synchronous, close of the connection. The abort method on the other hand is for abruptly terminating a connection that may be stuck.
In most cases you will need to use close(), but close() can sometimes not complete in time, for example it could block if the connection is currently busy (eg executing a long running query or update, or maybe waiting for a lock).
The abort method is for that situation: the driver will mark the connection as closed (hopefully) immediately, the method returns, and the driver can then use the provided Executor to asynchronously perform the necessary cleanup work (eg making sure the statement that is stuck gets aborted, cleaning up other resources, etc).
I hadn't joined the JSR-221 (JDBC specification) Expert Group yet when this method was defined, but as far as I'm aware, the primary intended users for this method is not so much application code, but connection pools, transaction managers and other connection management code that may want to forcibly end connections that are in use too long or 'stuck'.
That said, application code can use abort as well. It may be faster than close (depending on the implementation), but you won't get notified of problems during the asynchronous clean up, and you may abort current operations in progress.
However keep in mind, an abort is considered an abrupt termination of the connection, so it may be less graceful than a close, and it could lead to unspecified behaviour. Also, I'm not sure how well it is supported in drivers compared to a normal close().
Consulting the java docs seems to indicate that abort is more thorough than close, which is interesting.
abort...
Terminates an open connection. Calling abort results in: The
connection marked as closed Closes any physical connection to the
database Releases resources used by the connection Insures that any
thread that is currently accessing the connection will either progress
to completion or throw an SQLException.
close...
Releases this Connection object's database and JDBC resources
immediately instead of waiting for them to be automatically released.
Calling the method close on a Connection object that is already closed
is a no-op.
So it seems if you are only concerned with releasing the objects, use close. If you want to make sure it's somewhat more "thread safe", using abort appears to provide a more graceful disconnect.
Per Mark Rotteveel's comment (which gives an accurate summary of the practical difference), my interpretation was incorrect.
Reference: https://docs.oracle.com/javase/8/docs/api/java/sql/Connection.html#close--
Related
Everywhere we see that the Statement.close() is 'handled' by eating up the exception that it throws. What are the cases where it can throw an exception in the first place? And what does it mean for the connection with which this statement was created?
In other words, when does statement.close() throw an exception and would the connection still be 'healthy' to be used for creating new statements?
Also, what happens if resultset.close() throws?
First, consider what the close() method might need to do, and what might cause an exception.
E.g. a PreparedStatement might have created a stored procedure, which needs to be deleted by the close() method. executeQuery() may have opened a cursor, which is used by the ResultSet, and close() needs to close that cursor.
Exception could of course be an internal error, but is most likely a communication error, preventing the close operation from succeeding.
So, what does that mean? It means that resources are not being explicitly cleaned up. Since your operation is already complete, it's generally ok to ignore those close() exceptions, since resources will be reclaimed eventually anyway.
However, since the cause is probably a communication error, the connection is likely broken, which means that you'll just get another exception on whatever you try next, making it even less likely that your handling of the close() exception matters.
To be safe, an exception means that something is wrong, and unless you examine the exception to understand how bad it is, you should abort whatever you're doing. A new connection should be established if you want to try again.
But, as already mentioned, ignoring close() exceptions aren't really a big issue. It may lead to resource leaks, but if the problem is bad, you're just going to get another exception on your next action anyway.
Simplest case for such an exception: the connection, that handled the statement is closed before you are trying to close the statement or if the statement was closed -somehow- already. speaking for jdbc, the connection should be healthy.
In general: As Peter stated, if the documentation of the driver does not contain any recommendations how to handle such an exception, you can only log or debug it. maybe you could re-establish the connection to be sure it is healthy.
When you close a statement, a lot of things can happen. These basic things can happen when closing a statement:
The open result set - if any - is closed, which may require communication to the database
The statement handle on the database server is released, which requires communication to the database
Given this involves communication to the database, all kinds of errors can occur: file system errors, network connection problems, etc. These may be safe to ignore, but could also indicated something very wrong with your application or database.
A secondary effect of a statement close can be a transaction completion (a commit or rollback). This could - for example - happen in auto-commit mode when you execute a data-modifying statement that produces a result set: the transaction ends when the result set is closed by the close of the statement. If this transaction commit fails, and you ignore it, your application may have just had a data-loss event (because the data was not persisted), and you just went ahead and ignored it.
In other words: you should not just ignore or swallow exceptions from Statement.close() unless you are absolutely sure there will be no detrimental effects. At minimum log them so you can trace them in your logs (and maybe define alerts on the number of exceptions logged), but always consider if you need to wrap them in application-specific exceptions and throw them higher up the call chain for handling, or - for commit failures - if you need to retry anything.
I was reading my database access logic, and found that it was possible for the same connection to be closed twice in a row.
Other than being a duplicate instruction, is there any reason I should be concerned about closing a connection after it's already been closed?
If you are using the java.sql.Connection you should have no issue.
From the Connection documentation:
Calling the method close on a Connection object that is already closed
is a no-op.
i.e. it does nothing.
This should stand for any proper implementation. Although it is conceivable for some implementation to have odd behavior on this matter.
From the documentation:
Releases this Connection object's database and JDBC resources
immediately instead of waiting for them to be automatically released.
Calling the method close on a Connection object that is already closed
is a no-op. 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.
So in short it is supposed to do nothing. Be aware though that a sloppy implementation for this Connection interface might fail to meet the rules defined in this interface's contract. You did not say which database are you using so I cannot provide further information on the implementation details.
So I have a Java process that runs indefinitely as a TCP server (receives messages from another process, and has onMsg handlers).
One of the things I want to do with the message in my Java program is to write it to disk using a database connection to postgres. Right now, I have one single static connection object which I call every time a message comes in. I do NOT close and reopen the connection for each message.
I am still a bit new to Java, I wanted to know 1) whether there are any pitfalls or dangers with using one connection object open indefinitely, and 2) Are there performance benefits to never closing the connection, as opposed to reopening/closing every time I want to hit the database?
Thanks for the help!
I do NOT close and reopen the connection for each message.
Yes you do... at least as far as the plain Connection object is concerned. Otherwise, if you ever end up with a broken connection, it'll be broken forever, and if you ever need to perform multiple operations concurrently, you'll have problems.
What you want is a connection pool to manage the "real" connections to the database, and you just ask for a connection from the pool for each operation and close it when you're done with it. Closing the "logical" connection just returns the "real" connection to the pool for another operation. (The pool can handle keeping the connection alive with a heartbeat, retiring connections over time etc.)
There are lots of connection pool technologies available, and it's been a long time since I've used "plain" JDBC so I wouldn't like to say where the state of the art is at the moment - but that's research you can do for yourself :)
Creating a database connection is always a performance hit. Only a very naive implementation would create and close a connection for each operation. If you only needed to do something once an hour, then it would be acceptable.
However, if you have a program that performs several database accesses per minute (or even per second for larger apps), you don't want to actually close the connection.
So when do you close the connection? Easy answer: let a connection pool handle that for you. You ask the pool for a connection, it'll give you an open connection (that it either has cached, or if it really needs to, a brand new connection). When you're finished with your queries, you close() the connection, but it actually just returns the connection to the pool.
For very simple programs setting up a connection pool might be extra work, but it's not very difficult and definitely something you'll want to get the hang of. There are several open source connection pools, such as DBCP from Apache and 3CPO.
Basically I do:
CONNECTION_POOL = new BoneCP(config);
And then right after:
CONNECTION_POOL.getConnection().createStatement("SELECT * FROM myTable");
which will sometimes (not always) throw a org.apache.derby.iapi.error.ShutdownException. I suspect there is some kind of racing condition or threading issue with BoneCP and it's instantiation, but I can't find anything anywhere. I did see something about lazy instantiation, but setting it to true or false makes no difference.
Any help would be greatly appreciated.
An embedded Derby database is shut down using a call to getConnection with the shutdown property set true. This will shut down the database AND throw a ShutdownException. Nothing is wrong, but according to jdbc getConnection is only allowed to return a valid connection or throw an exception. And since there cannot be a valid connection to a database that has been shut down, and exception must be thrown. So the question here really is if the framework you use is supposed to catch this exception, or if you are supposed to handle it.
Calling Thread.interrupt will cause derby to shutdown in some cases. To quote the Derby Guide: "As a rule, do not use Thread.interrupt() calls to signal possibly waiting threads that are also accessing a database, because Derby may catch the interrupt and close the connection to the database. Use wait and notify calls instead."
This is actually bad because some libraries will call Thread.interrupt and so on. And in some cases it's good practice depending on what you're doing. In my opinion this is a big design flaw of the database engine.
In any case the only solution I found was that if you're going to call Thread.interrupt(), then you need to adjust the Derby source code to ignore these thread interruptions. Specifically the method noteAndClearInterrupt(...) in the class org.apache.derby.iapi.util.InterruptStatus
I have lots of method in my database class that all of them have one statement, when should I close the connection? In each method or at the end of database class?
You should close the connection when you are finished your transaction. Since we don't know the contents of the class or its usage, it's impossible to tell when your access of the connection begins or ends.
Actually, that may not even be true if the connection is dedicated for a specific usage and not in a pool. You may want to keep it open for the duration of your application.
We've found that the best policy is to get a connection from the connection pool, execute a single transaction, and then put the connection back into the pool immediately. This way you don't have a connection being held onto for long blocks of logic, thus preventing other threads from using it - which is an issue for scalability.
As a best practice, you should close the connection in the logical place after you are done - right after all of database activity for that task is done.
Generally, you should close a connection in the same method that opens it. Closing and opening connections isn't an arduous task, since modern DB servers keep even closed connections on "hot standby", so they are quickly accessed through a connection pool. Leaving them open though...that can get you in trouble and can be a nightmare to debug.
use lombok and it will handle both try/catch and conn.close() for you
public void doSomething() throws SQLException {
#Cleanup Connection connection = database.getConnection();
}
lombok
It depends when and how repeatedly you are using these methods. If they are sequential you should close the connection only in the end, instead of open and close often
This largely depends on what your Database class does. If your methods are called individually at various times then the methods should be responsible for opening and closing the connection. However, if the class does some kind of big processing operation that calls many methods then you may want to open and close the connection outside of the individual methods.
The most important thing is that wherever you open the connection, you also close the connection. Otherwise you get into the business of making assumptions about the state of the connection which can get you into trouble.
Close the connection (and statement and resultset!) in the same method block as you've acquired it, in the finally block of the try block where they are opened.
The general idiom is:
public void doSomething() throws SQLException {
Connection connection = null;
try {
connection = database.getConnection();
} finally {
if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
}
Closing of connection, statement and resultset should happen in reversed order as they're opened.
If your actual concern is performance, then consider using a connection pool to improve connecting performance, for example C3P0. This by the way does not change the general idiom. Just continue writing the same idiom, the connection pooling implementation will worry itself further under the hoods.
Also see this article for more practices/examples.
Always close the connection when you finish executing your transaction. It is a good practice to obtain and close your connection in the same method. If you have separate transactions that are tightly coupled you might execute them with the same connection, but for best practices, I try to execute one transaction per connection.
If it is an option, don't explicitly mess with connections at all. Use a full blown orm framework like hibernate or use something significantly more lightweight like spring jdbc templates.
It depends somewhat on the context your application operates in. If it's a web app you need to be careful to open your connection, do whatever work is needed, and close the connection quickly. However, in a C/S or batch environment it may be better to acquire the connection and hold onto it as long as the user is interacting "frequently" (for whatever value of "frequently" you choose), especially if the user has expectations of rapid response time and it's expensive (in terms of time or resources) to acquire the connection to your particular variety of database.
I like to set a timer every time the user has the app go to the database. If/when the timer expires, close the connection, then re-open the next time he/she/it wants to hit the database again. Timer expiration can be somewhere between 1 and 20 minutes. Just so long as it's less than the database's "inactivity disconnect" time.
Share and enjoy.