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.
Related
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.
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.
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(...)) {...}
[Java 7/Oracle] I have a multi-threaded application in which I plan to use a database connection pool. I would like to use prepared statements; however, it seems that prepared statements contain and would therefore seem to be inextricably bound to a single database connection object. The paradigm I want is NOT "open a connection, prepare a statement, do the same query thousands of times, then close the connection" as seems to be the sample code everywhere; the paradigm I want is "precompile this statement so it is run as efficiently as possible - get a random connection from the pool - execute the statement against that connection - release the connection back to the pool". Is this even possible in Java?
If you use a connection pool then connections are not actually closed when you call close on the conneciton object. Instead it is returned to the pool. This is usually achieved by wrapping the original connection in a proxy which intercepts your call to close.
Many connection pools and some drivers offer the possibiity to cache prepared statements to remedy the problem of continuously preparing the same statements. Of course, because the prepared statement is linked to the connection, you probably will preprare the same statement for every connection in the pool.
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.