Which should I close first, the PreparedStatement or the Connection?
The statement. I would expect you to close (in order)
- the result set
- the statement
- the connection
(and check for nulls along the way!)
i.e. close in reverse order to the opening sequence.
If you use Spring JdbcTemplate (or similar) then that will look after this for you. Alternatively you can use Apache Commons DbUtils and DbUtils.close()
or DbUtils.closeQuietly()
.
When to close connection in JDBC/SQL
The 1st approach is correct, It's good programming practice to explicitly close things that you open once you've finished with them.
Generally you should Close the connection in a finally block. All other JDBC resource depend on this so are freed up implicitly...
Must JDBC Resultsets and Statements be closed separately although the Connection is closed afterwards?
What you have done is perfect and very good practice.
The reason I say its good practice... For example, if for some reason you are using a "primitive" type of database pooling and you call connection.close()
, the connection will be returned to the pool and the ResultSet
/Statement
will never be closed and then you will run into many different new problems!
So you can't always count on connection.close()
to clean up.
I hope this helps :)
Relationship between close for PreparedStatement and Connection?
Closing a Statement
doesn't close a Connection
. However, closing a Connection
will close a Statement
.
Think of it like so:
- Connection -> creates and automatically closes -> Statement
- Statement -> creates and automatically closes -> ResultSet
So closing a Connection
will automatically close any Statement
s and any ResultSet
s it contains.
However, it's still considered best practice to close all three manually (ResultSet
followed by Statement
followed by Connection
) if possible.
Do I need to close 'PreparedStatement'?
Yes, you have to close the prepared statements (PreparedStatement
Object) and result sets as they may cause memory leakage.
For more information, see Using Prepared Statements.
Try-with-resources - Does it automatically close the connection? Java
No, the try with resources does not close the Connection
that is used inside the PreparedStatement
.
Only the PreparedStatement
and its ResultSet
are closed.
When a Statement object is closed, its current ResultSet object, if one exists, is also closed.
It is possible to reuse a connection
to execute many PreparedStatements
. Each of which is closed after usage. When the connection
is no longer needed it can be closed as well.
You could perhaps check it like this:
public void query(String queryString, List<String> queryParams, Consumer<ResultSet> sqlConsumer)
{
Connection connection;
try (PreparedStatement preparedStatement = this.configureStatement(queryString, queryParams))
{
connection=preparedStatement.getConnection();
sqlConsumer.accept(preparedStatement.executeQuery());
} catch(SQLException exception)
{
exception.printStackTrace();
}
if(connection!=null){
System.out.println("Is Connection closed:"+connection.isClosed());
}
}
private PreparedStatement configureStatement(String query, List<String> queryParams) throws SQLException
{
PreparedStatement preparedStatement = this.getConnection().prepareStatement(query);
for (int i = 0; i < queryParams.size(); ++i)
preparedStatement.setString(i, queryParams.get(i));
return preparedStatement;
}
A refactoring that closes connections by using the try-with-resources with multiple statements:
public void query(String queryString, List<String> queryParams, Consumer<ResultSet> sqlConsumer)
{
try ( Connection connection=this.getConnection();
PreparedStatement preparedStatement = this.configureStatement(connection, queryString, queryParams);)
{
sqlConsumer.accept(preparedStatement.executeQuery());
} catch(SQLException exception)
{
exception.printStackTrace();
}
if(connection!=null){
connection.close();
}
}
private PreparedStatement configureStatement( Connection connection,String query, List<String> queryParams) throws SQLException
{
PreparedStatement preparedStatement = connection.prepareStatement(query);
for (int i = 0; i < queryParams.size(); ++i)
preparedStatement.setString(i, queryParams.get(i));
return preparedStatement;
}
How often should Connection, Statement and ResultSet be closed in JDBC?
Always. You need to acquire and close them in the shortest possible scope to avoid resource leaking, transactional problems and exhausted connection pools. Not doing so would cause the DB to run out of resources sooner or later, resulting in exceptions like "Too many connections".
The normal JDBC idiom is the following, whereby all resources are opened and closed in the very same try-with-resources block:
public List<Entity> list() throws SQLException {
List<Entity> entities = new ArrayList<Entity>();
try (
Connection connection = database.getConnection();
PreparedStatement statement = connection.prepareStatement(SQL_LIST);
ResultSet resultSet = statement.executeQuery();
) {
while (resultSet.next()) {
entities.add(map(resultSet));
}
}
return entities;
}
Or when you're not on Java 7 yet:
public List<Entity> list() throws SQLException {
List<Entity> entities = new ArrayList<Entity>();
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;
try {
connection = database.getConnection();
statement = connection.prepareStatement(SQL_LIST);
resultSet = statement.executeQuery();
while (resultSet.next()) {
entities.add(map(resultSet));
}
} finally {
if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
return entities;
}
Using PreparedStatement
will give you the benefit of the DB caching of the statements (next to SQL injection prevention when used properly). Acquiring and closing the connection is the most expensive task, but there the connection pools are invented for. If you want to reuse the same statement to do bulk inserts/updates, then you can use batches.
See also:
- When my app loses connection, how should I recover it?
- Is it safe to use a static java.sql.Connection instance in a multithreaded system?
Closing Connection, PreparedStatement, and ResultSet all in one call
Practice the Best Practice
Yes, their is a problem in closing connection the way you have closed.
Suppose, an exception occurred while closing ResultSet object the rest things would not be closed
Second, suppose if everything goes fine, still you are holding other connection (etc) you are not using, it adds to the burden to the JVM, Database, Memory manager etc
It is recommended to use " try(){} with resource " feature available in JAVA 7 or if you are using JAVA 6 close them when it is no longer needed.
Related Topics
How to Pass Arithmetic Operators to a Method in Java
Changing the Shapes of Points in Scatter Plot
How to Format a Java String with Leading Zero
How to Check If Multiplying Two Numbers in Java Will Cause an Overflow
Can the Jvm Recover from an Outofmemoryerror Without a Restart
How to Fix Ambiguous Type on Method Reference (Tostring of an Integer)
Spring Java Config: How to Create a Prototype-Scoped @Bean with Runtime Arguments
Converting Integers to Roman Numerals - Java
Sorting a List of Points with Java
Populating Spring @Value During Unit Test
Are "While(True)" Loops So Bad
Open a Link in Browser with Java Button
Why Are the Rsa-Sha256 Signatures I Generate with Openssl and Java Different
Does Java Have Built in Libraries for Audio _Synthesis_
How to Get Information About the Local Variables Using Java Reflection