Prepared Statements along with Connection Pooling
I have a question regarding general use of Prepared Statement along with connection pooling.
Prepared Statements are generally tied to one connection only.In our application, a PreparedStatement is created 开发者_运维问答at the start up and executed at a later point.
If at the time of execution of some specific prepared statement, connection associated with the prepared statement is busy executing other statements than how this required statement will get executed.Does this statement will wait for connection to get free or this statement will be given preference in execution?
Update
I have tested this by following SLEEP() function with Apache derby database which calls java function sleep in class TimeHandlingTest.
CREATE FUNCTION SLEEP() RETURNS INTEGER LANGUAGE JAVA PARAMETER STYLE JAVA NO SQL EXTERNAL NAME 'com.derby.test.TimeHandlingTest.sleep';
And made two prepared statements from one connection and called Sleep() function from one prepared statement and simple sql select with other.Simple sql select took almost same time(10s) for which first prepared statement was sleeping.This means that one connection object cannot be used for execution by more than one prepared statement at a time.Please correct me if i am wrong.
You can't return the Connection
to the pool if you plan on using the PreparedStatement
.
In other words: you can only use a PreparedStatement
constructed from a Connection
that you currently have.
The value of PreparedStatement lies in the ability of the database itself to create an execution plan for the statement that can be reused for arbitrary parameters and thus is generic in nature (of course that requires that you use parameters in your statetment, e.g.
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00);
pstmt.setInt(2, 110592);
If on the other hand you would use string concatenation to paste the parameter values into the SQL code, the database would not be able to build a generic execution plan. Thus it would make no difference if you use a PreparedStatement or Statement, e.g.
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
SET SALARY = 1200 WHERE ID = 3");
would not be able to use the advantage of PreparedStatements.
Your question implies, that you want to reuse the PreparedStatement object, which is not necessary. Of course if you can use a PreparedStatement object to update multiple values etc. it is a more efficient use of ressources. Nevertheless the lifespan (or at least usefull lifespan) of the PreparedStatement is tied to the Connection, thus if you call conn.close() the PreparedStatement is rendered useless. Nevertheless most good drivers in a pooling situation reuse the same PreparedStatement objects again. In short, don't cache the PreparedStatement independent of the connection.
Assuming that this is a multi-threaded application, Connection
objects are typically associated with a single thread at any instant of time. Connection
objects acquired by a thread are not returned to the pool until they are closed. This applies both to the logical connection wrapper (that is typically returned by a DataSource managed by an application server) to the application, as well as to the physical connection. Also, physical connections can be shared across multiple logical connections as long as they are part of the same transaction.
This means that if a logical connection handle is returned to your application, it is not necessary that the underlying physical connection is the same and is being contended for (unless it is part of the same transaction). If your application is expected to handle concurrent users without any hassle, a Connection
object would be created in every thread starting a transaction, and this object would not be contended for, across threads. Under the hood, different physical connections in the pool would be executing the SQL queries associated with the prepared statements, across multiple threads, again without any contention.
This sounds like an unusual way to use your connection pool. Even though the connections are in a pool, they should only be used by one thread at a time. I tend to create the prepared statement and use it very close to the point of creation. Also, some JDBC drivers now support Statement caching which reduces the overhead of using it in this way.
One way around this is to maintain a cache where connections are mapped to prepared statements. When you get a connection from the pool check if it is mapped to the prepared statement that is to be executed. If not, pass the prepared statement to the JDBC driver so that it is compiled. Then map it to the connection. The downside of this approach is that more than one connection might get copies of the same prepared statement. But it seems that this is what some J2EE servers do.
精彩评论