Closing a DB connection in Java - java

Its just a foolish queation from a java programmer.
I have something like
PreparedStatement stmt = DBConnection.getConnection()
.prepareStatement(sql);
Now in finally block I check if stmt exists and then close it. What will happen to Connection object in this case. I know if I write in separate lines then I can close it as I have a reference to connection object which I don't have in this case.

What will happen to Connection object in this case.
Nothing. There is no magic, so the connection isn't magically closed, just because you didn't assign it to a variable.
That's why you use a separate variable for the Connection: so you can call close()! Or use try-with-resources:
try (Connection connection = DBConnection.getConnection()) {
PreparedStatement stmt = connection.prepareStatement(sql);
}

The connection will remain open until it is garbage collected at some time in the future.
However, in the case of connection pools, yours might not be the only reference to the Connection (if the pool also maintains a reference to connections which have been borrowed). In this case garbage collection will not take place, and the collection will not be closed. It will have "leaked" from the pool, which will likely eventually cause the pool to be exhausted and no further connections will be available.

Related

Am I closing the DB connection correctly? JDBC - DBCP

Will closing the preparedStatement also close and return the connection to the connection pool?
public void insertProjectIntoDatabase(Project project) {
String insertProjectIntoDatabase =
"INSERT INTO projects(Project_Id, Project_Name, Project_StartDate, Deadline) " +
"VALUES (?, ?, ?, ?)";
try {
preparedStatement = DBCPDataSource.getConnection().prepareStatement(insertProjectIntoDatabase);
preparedStatement.setInt(1, project.getProjectId());
preparedStatement.setString(2, project.getName());
preparedStatement.setDate(3, java.sql.Date.valueOf(project.getStartDate()));
preparedStatement.setDate(4, java.sql.Date.valueOf(project.getDeadline()));
preparedStatement.execute();
preparedStatement.close();
}
catch (SQLException e)
{
System.out.println("Error happened in ProjectRepository at insertProjectIntoDatabase(): " + e.getMessage());
}
}
Bonus question:
I have created performance tests for creating a new connection each time an object needs one, Singleton connection and connection pool.
Singleton - Fastest
Creating a new connection each time - Slower (1.2s than the one above)
Connection Pool - Slowest (First connection - 2-3s slower than the one above, following tests are 0.4s slower than the one above)
I am using Apache Commons DBCP for the connection pool.
I thought using connection pools, would be just a little slower than Singleton connection.
Have I done something wrong?
You asked:
Will closing the preparedStatement also close and return the connection to the connection pool?
Start with the documentation:
Releases this Statement object's database and JDBC resources immediately instead of waiting for this to happen when it is automatically closed. It is generally good practice to release resources as soon as you are finished with them to avoid tying up database resources.
Calling the method close on a Statement object that is already closed has no effect.
Note:When a Statement object is closed, its current ResultSet object, if one exists, is also closed.
No mention of closing the connection.
Try intuition: Do we ever run more than one statement in SQL? Yes, obviously. So logically the connection needs to survive across multiple statements to be useful.
Lastly: Try it yourself, an empirical test. Call Connection#isOpen after calling Statement#close.
➥ No, closing the statement does not close the connection.
For the simplest code, learn to use try-with-resources syntax to auto-close your database resources such as result set, statement, and connection. You’ll find many examples of such code on this site, including some written by me.
As for connection pools, yes, calling close on a connection retrieved from a pool causes the connection object to be be returned to the pool. The pool may choose to re-use the connection, or the pool may choose to close the connection. (Not our concern.)
The only point to a connection pool is speed. If opening a connection to the database takes a significant amount of time, we can save that time by re-using existing connection. Generating and re-using connections is the job of a connection pool.
If a connection pool is showing the slowest results in your testing, then here is something seriously wrong with either your pool or your tests. You did not reveal to us your tests, so we cannot help there. Note: As Marmite Bomber commented, be sure your tests do not include the time needed to establish the connection pool.
Frankly, I have found in my experience that opening a database connection does not take a significant amount of time. Furthermore, the details involved in properly implementing a connection pool are complex and treacherous as evidenced by the list of failed and abandoned connection pool implementation projects. That, combined with the inherent risks such as a transaction being left open on a retrieved connection, led me to avoiding the use of connection pools. I would posit that using a connection pool before collecting proof of an actual problem is a case of premature optimization.
I suggest using an implementation of the interface DataSource as a way to mask from the rest of your code whether you are using a pool and to hide which pool implementation you are currently using. Using DataSource gives you the flexibility to to change between using or not using a connection pool, and the flexibility to change between pools. Those changes become deployment choices, with no need to change your app programming.
Pools are meant to improve performance, not degrade it. DBCP is naive, complicated, and outdated.
I don't think it's appropriate for a production application, especially when so many drivers support pooling in their DataSource natively. The entire pool gets locked the whole time a new connection attempt is made to the database. So, if something happens to your database that results in slow connections or timeouts, other threads are blocked when they try to return a connection to the pool—even though they are done using a database.
Even C3PO performs terribly.
Please try using one of the two connection pools tomcat_connection_pool or HikariCP
Now coming to your main part of the question if you have closed the connection correctly?
Whenever you use a connection pool and you fetch an available connection from the pool you need not have to close the connection that you fetched in your Dao layer. The pool manages the connections that you have created and each connection that the pool lends has a timeout associated with it before which it has to return to the pool. When the pool is shut down all the connections shutdown too.
For more information on how to configure these properties in your connection pool. Please check the links above for each of the connection pools.

Should I close a Connection obtained from a DataSource manually?

When I get a Connection from the DataSource, should I close it manually? I mean in case I must close it, how it will be used in future requests?
A connection obtained from a connection pool should be used exactly the same as a normal connection. The JDBC 4.2 specification (section 11.1) says about pooling:
When an application is finished using a connection, it closes the logical connection
using the method Connection.close. This closes the logical connection but does
not close the physical connection. Instead, the physical connection is returned to the
pool so that it can be reused.
Connection pooling is completely transparent to the client: A client obtains a pooled
connection and uses it just the same way it obtains and uses a non pooled
connection.
(emphasis mine)
This means that when you are done with a connection, you always call Connection.close()! It doesn't matter if it is a physical connection, or a logical connection from the pool.
The reason is that whether a connection is a physical (direct) connection or a logical connection should be purely a matter of configuration, not a concern of the application code that merely uses the connection.
In the case of a connection pool, the close() will - details may vary, and some implementations are buggy in this respect - invalidate the logical connection and signal to the connection pool that the underlying physical connection is available for re-use. The connection pool may do some validity checks and then return the (physical) connection into the pool or close it (eg if the pool has too many idle connections, or the connection is too old, etc).
Calling close() is not only allowed, it is even vital for the correct working of a connection pool. Not calling close() usually requires some helper thread to close (reclaim) logical connections that have been in use for too long. As this timeout is usually longer than normal application needs, it might lead to exhaustion of the pool, or to configuration where the pool needs a higher maximum number of connections than is really necessary.
You should close Connection in order to return it to the pool, next time you'll ask for Datasource.getConnection() connection from the pool will be obtained. There is no problem here.
Sometimes you don't want to close connection after each operation and use the same connection for several operations. In this case you shouldn't close it until last operation finished.
Use try with resources to avoid connection problems
try (Connection con = ds.getConnection();
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(...)) {...}

Database connections in connection pool

For a code similar to this,
try{
Connection con =....
Statement stmt = ....
ResultSet set = ...
}
catch(Exception e){
...
}
finally {
con.close();
}
Given that the connection goes to a connection pool:
When con.close() is called, it goes to the connection pool and remains active. At one point of time, these connections get closed right? In that case, do we need to close result set and stmt objects as the connection will eventually get closed?
Also, can there be a situation where the stmt/result set objects might still be used and causing the connection in connection pool not getting closed?
It's recommended to release resources as soon as they are not needed anymore.
The easiest way is to use the new try-with-resources feature (Java SE 7).
When you are using connection pooling, Connection.close() invocation would put the connection back to the pool. The Statement objects will be removed when you call Connection.close(). But, AFAIK, you have to close the ResultSet objects to clear them from server explicitly. it's a good way to always close ResultSet,Statement explicitly and not to rely on Connection.close().Adding to that, if you may opt for Spring JDBC, it will take care of managing the JDBC resources. You don't have to worry about closing connections, statements and resultsets. Adding to that, from Statement API - When a Statement object is closed, its current ResultSet object, if one exists, is also closed.

Preferred way to query a database multiple times?

When using JDBC in Java, the generally accepted method of querying a database is to acquire a connection, create a statement from that connection, and then execute a query from that statement.
// load driver
Connection con = DriverManager.getConnection(..);
Statement stmt = con.createStatement();
ResultSet result = stmt.executeQuery("SELECT..");
// ...
However, I am unsure of how to treat a second query to the same database.
Can another query be executed safely on the same Statement object, or must another statement be created from the Connection object in order to execute another query?
If the same Statement object can be used for multiple queries, what is the purpose of the Statement class (since it would then make more sense for a Connection.executeQuery() method to exist)?
Yes you can reuse the Statement object, but the ResultSet objects returned by the executeQuery closes already opened resultsets.
See the javadoc for the explanation
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.
So the following occurs:
// load driver
Connection con = DriverManager.getConnection(..);
Statement stmt = con.createStatement();
ResultSet result = stmt.executeQuery("select ..");
// do something with result ... or not
ResultSet result2 = stmt.executeQuery("select ...");
// result is now closed, you cannot read from it anymore
// do something with result2
stmt.close(); // will close the resultset bound to it
For example you can find an open source implementation of Statement in the jTDS project.
In the Statement.executeQuery() method you can see a call to initialize() that closes all the resultsets already opened
protected void initialize() throws SQLException {
updateCount = -1;
resultQueue.clear();
genKeyResultSet = null;
tds.clearResponseQueue();
// FIXME Should old exceptions found now be thrown instead of lost?
messages.exceptions = null;
messages.clearWarnings();
closeAllResultSets();
}
Programmatically, you can reuse the same connection and the same statement for more than one query and close the statement and the connection at the end.
However, this is not a good practice. Application performance is very sensitive to the way database is accessed. Ideally, each connection should be open for the least amount of time possible. Then, the connections must be pooled. Going by that, you would enclose each query in a block of {open connection, create a prepared statement, run query, close statement, close connection}. This is also the way most SQL Templates are implemented. If concurrency permits, you can fire several such queries at the same time using a thread pool.
I have one thing to add should you use Connection and Statement in a threaded environment.
My experience shows that stmt.executeQuery(..) is save to use in a parallel environment but with the consequence that each query is serialized and thus processed sequencially, not yielding any speed-ups.
So it es better to use a new Connection (not Statement) for every thread.
For a standard sequential environment my experience has shown that reusing Statements is no problem at all and ResultSets need not be closed manually.
I wouldn't worry about creating new statements. However opening up a database connection may be resource intensive and opening and closing connections does impact performance.
Leaving up connections in some self management way usually is pretty bad.
You should consider using connection pooling. You usually issue a close commando however you are only giving that connection back to the pool. When you request a new connection then it will reuse the connection you gave back earlier.
You may want to have different statements for one connection. Statement is an implementation and an interface. Depending on what you need you sometimes want a use a CallableStatment. Some some logic may be reused when required.
Usually, it's one statement for one query. It might not be necessary to do that but when writing real application, you don't want to repeat those same steps again and again. That's against the DRY principal, plus it also will get more complicated as the application grows.
It's good to write objects that will handle that kind of low level (repetitive) stuffs, and provide different methods to access db by providing the queries.
Well that's why we have the concept of classes in object oriented programming . A class defines constituent members which enable its instances to have state and behavior. Here statement deals with everything related to an sql statement. There are so many more function that one might perform like batch queries etc.

What happens with the Statement when ResultSet is closed?

What happens with the statement when result set is closed?
Statement stmt = null;
ResultSet rs = null;
try {
stmt = con.createStatement();
rs = stmt.executeQuery(query.toString());
...
}
// lots of code
rs.close()
Note: A ResultSet object is automatically closed by the Statement
object that generated it when that Statement object is closed,
re-executed, or is used to retrieve the next result from a sequence of
multiple results.
But what happens when ResultSet is closed first?
For what matter, what should happen first?
You should close the objects in the reverse order of creating them.
So first, the ResultSet, then the Statement and in the end, Connection.
If you don't close the Statement it stays open and you can execute another query with it (if it's a PreparedStatement or CallableStatement you are able to change query parameters).
Also note, that what you quoted is a JDBC specification, and the implementation of it is up to a JDBC driver provider. Usually, you should not trust them, and manually close those objects.
The other thing - I think more important - if you are using connection pools (like on JBoss), closing connection just releases it back to the pool, and the underlying objects are not released. And because of this, its recommended to always manually release all the objects you created.
The Statement actually can be reused. Though if you're repeating the same query, you should use a PreparedStatement instead as the query will be compiled once.
They of course should be closed when you're done with them, but closing the ResultSet doesn't automatically close the Statement for good reason.
Nothing happens to the Statement -- it stays open. You can continue to use the Statement however you'd like, but be sure to close it when you're finished.

Categories