In the tutorial "Using Prepared Statements" it states that they should always be closed. Suppose I have a function
getPrice() {
}
that I expect to be called multiple times per second. Should this method be opening and closing the PreparedStatement with every single method call? This seems like a lot of overhead.
First of all, PreparedStatement are never opened. It's just a prepared Statement that is executed. The statement is sent to the RDBMS that executes the SQL statement compiled by the PreparedStatement. The connection to the SQL statement should be opened during the duration of the SQL querying and closed when no other RDMS calls is needed.
You can send many Statement/PreparedStatement as you require provided that you finally close its ResultSet and PreparedStatement once you're completed with them and then close the RDBMS connection.
Should this method be opening and closing the PreparedStatement with every single method call?
If you are creating the PreparedStatement object within the method, then you must close it, once you are done with it. You may reuse the PreparedStatement object for multiple executions, but once you are done with it, you must close it.
This is because, although all Statement objects (including PreparedStatements) are supposed to be closed on invoking Connection.close(), it is rarely the case. In certain JDBC drivers, especially that of Oracle, the driver will be unable to close the connection if the connection has unclosed ResultSet and Statement objects. This would mean that, on these drivers:
You should never lose a reference to a PreparedStatement object. If you do, then the connection will not be closed, until garbage collection occurs. If you are reusing PreparedStatement instances for different SQL statements, it is easy to forget this.
You should close the PreparedStatement once you no longer need it. Only then can the Connection.close() actually tear down the physical connection.
As the example in the tutorial shows you should close it after all your queries have been performed.
Once the statement is closed the RDMS may release all resources associated with your statement. Thus to use it further you'd have to re-prepare the very same statement.
I think that, after every database interaction, every component like statement, resultset must be closed, except for connection, if u tend to perform more operation.
And there is no need to worry, if you are creting the prepared statement again and again, because as you will be using the same statement again and again, there wont be any performannce issue.
Yes..No issues are there if you are creating the prepared statement n number of times, because as you will be using the same statement at all the places. No need to have any observation here regarding performance
Thanks
Related
PreparedStatment ps = null;
public void executeQueries(){
try{
ps = conn.prepareStatement(Query1);
// Execute Query1 here and do the processing.
ps = conn.prepareStatement(Query2);
// Execute Query2 here and do the processing.
//... more queries
}catch(){}
finally{
ps.close(); // At this point would the caching of queries in DB be lost?
}
}
In my Application, I call the method executeQueries() frequently.
My question is, If I close the PreparedStatement in the finally block inside the method (that I use frequently), would the database system remove the caching? If YES, can I make a global PreparedStatement for the entire application as there are loads of JAVA CLASSES in my application that query the database.
Thank you!
Update : The question has been marked duplicate but the linked thread does not answer my question at all. AFAIK, the database system stores the executed queries in the cache memory. It also stores their execution plan. This is where PreparedStatement perfoms better than Statement. However, I am not very sure if the information related to the query is removed once the PreparedStatement is closed.
Specifically with regard to MySQL, according to
8.10.3 Caching of Prepared Statements and Stored Programs
The server maintains caches for prepared statements and stored programs on a per-session basis. Statements cached for one session are not accessible to other sessions. When a session ends, the server discards any statements cached for it.
So closing a PreparedStatement would not remove the statement(s) from the cache, but closing the Connection presumably would.
... unless the application uses a connection pool, in which case closing the Connection may not necessarily end the database session; it may keep the session open and just return the connection to the pool.
Then there's also the question of whether the statements are actually being PREPAREd on the server. That is controlled by the useServerPrepStmts connection string attribute. IIRC, by default, server-side prepared statements are not enabled.
I'm creating a server-side Java task that executes the same SQL UPDATE every 60-seconds forever so it is ideal for using a java.sql.PreparedStatement.
I would rather re-connect to the database every 60-seconds than assume that a single connection will still be working months into the future. But if I have to re-generate a new PreparedStatement each time I open a new connection, it seems like it is defeating the purpose.
My question is: since the PreparedStatement is created from a java.sql.Connection does it mean that the connection must be maintained in order to use the PreparedStatement efficiently or is the PreparedStatement held in the database and not re-compiled with each new connection? I'm using postgresql at the present, but may not always.
I suppose I could keep the connection open and then re-open only when an exception occurs while attempting an update.
Use a database connection pool. This will maintain the connections alive in sleep mode even after closing them. This approach also saves performance for your application.
Despite the connection that created the PreparedStatement, the SQL statement will be cached by the database engine and there won't be any problems when recreating the PreparedStatement object.
Set your connection timeout to the SQL execution time+few minutes.
Now, you can take 2 different approaches here -
Check before executing the update, if false is returned then open new Connection
if( connection == null || !connection.isValid(0)) {
// open new connection and prepared statement
}
Write a stored procedure in the Db, and call it passing necessary params. This is an alternate approach.
Regarding you approach of closing and opening db connection every 60 seconds for the same prepared statement, it does not sound like a good idea.
I am implementing a server with MySQL server.
I have come to a conclusion that all my queries will be sent using prepared statements.
I am going to make multiple singleton prepared statements for different purposes(For example, select token, insert/replace token, insert phone numbers ...).
Here are my questions.
For singleton prepared statements to perform well, should I close it every time I execute a query? (close only the ResultSet, not prepared statements or the connection)
Will singleton prepared statement be better than creating a statement every time?
Simple answer - create and close statement every time.
If you are not implementing a VERY specialized batch functionality, then creating and closing prepared statement will be an insignificant overhead.
Also having a singleton connection is not a good idea for server application. Only a single thread can work with one connection at any time.
I'm using c3p0. I set up a pooled as follows,
cpds = new ComboPooledDataSource();
cpds.setJdbcUrl(...);
/* connection setup */
spds.setMaxStatements(200);
I have an object that prepares several prepared statements on initialization. In order to do that, I grab a connection (con = getConnection()) from the PooledDataSource and then prepare a statement (e.g., PreparedStatement stmt = con.preparedStatemet(/*sql*/)). The prepared statements are stored as private variables in the object and the current connection is closed at the end of initialization (con.close()). The prepared statements are used in methods of the object.
For prepared statements that update the database, this works just fine. However, when I call a method that uses a prepared statement (stmt.executeQuery()) to query the database, I get the following SQLException
java.sql.SQLException: You can't operate on a closed Statement!!!
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:118)
at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:77)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeQuery(NewProxyPreparedStatement.java:127)
Did I get something wrong concerning the usage of c3p0?
Many thanks in advance!
Edit: Obviously, my question is partly based on my lack of understanding. As was pointed out in the definite answer, a PreparedStatement belongs to a connection and whenever the connection is closed, the associated statements should be closed, as well. But if that is the case, I don't understand what the use of c3p0's statement cache is.
you should get the same Exception calling executeUpdate(). JDBC Connection and Statement pooling is designed to be transparent: the same API that works for unpooled DataSources should be used for pooled versions too. There will be a dramatic difference in performance, but the code should be semantically interchangeable.
in an unpooled environment, it should be obvious why your approach fails: a Statement, prepared or otherwise, is a child of a Connection, without which it can't function. you are hoping that in the pooled environment, even though the Connection has been "closed", it should still exist in the pool, so hey, those Statements might be good. but that's a very bad idea (and if your attempts to do updates really are succeeding after the parent Connection has been close()ed, again, that'd be a bug, a bad one.) once a Connection has been "closed" it goes back in the pool, but not forever. other clients will check it out, and start performing transaction work that shouldn't be interrupted by your stale Statements. eventually Connections will be expired out of the pool. what should happened to your retained PreparedStatements then?
c3p0 pools Statements transparently, meaning you should use exactly the same API you would have used with no pooling. Call prepareStatement(...) on your Connection, every time. if you've enabled Statement pooling in c3p0 (as you have), then internally c3p0 will check to see whether the Statement has already been prepared, and if so it will quietly use the cached version rather than forwarding the request to the dbms.
i hope this helps!
I have made a java class which runs in it's own thread that works through a queue of mysql queries so that it doesn't block the main application thread. I want to use prepared statements, however if I keep reusing the same prepared statement then if there's two or more of that same prepared statement in the queue (I use the same preparedstatement object for each query of that type), it will have the wrong params. If I make a new preparedstatement each time will it recompile the prepared statement each time it is run or will it detect that it's already been compiled and just execute?
I think you really wont be able to utilize Prepared Statement Pooling feature available in Java connection pooling implementations like Apache DBCP. This is because you are storing prepared statement objects in the queue. If you could store your SQL and paramenters in a custom class instead, and create / execute PreparedStatements in execution thread you can get the benefit of pooling by using something like DBCP
See DBCP configurations docs on how to enable statement pooling (poolPreparedStatements)
will it recompile the prepared statement each time it is run or will
it detect that it's already been compiled and just execute?
It's up to the DBMS, not Java, but the general idea is that it can detect a reuse of an existing compiled statement and pools them under the hood, either in the driver or at the server. See the JDBC 4.0 Specification, #11.6, "Reuse of Statements by Pooled
Connections".
From the java tutorial
If you want to execute a Statement object many times, it usually reduces execution time to use a PreparedStatement object instead.
The main feature of a PreparedStatement object is that, unlike a Statement object, it is given a SQL statement when it is created. The advantage to this is that in most cases, this SQL statement is sent to the DBMS right away, where it is compiled. As a result, the PreparedStatement object contains not just a SQL statement, but a SQL statement that has been precompiled. This means that when the PreparedStatement is executed, the DBMS can just run the PreparedStatement SQL statement without having to compile it first.
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html#supply_values_ps