简体   繁体   English

准备好的语句以及连接池

[英]Prepared Statements along with Connection Pooling

I have a question regarding general use of Prepared Statement along with connection pooling. 我有一个关于Prepared Statement的一般用法以及连接池的问题。

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. 准备好的语句通常仅与一个连接相关联。在我们的应用程序中,PreparedStatement在启动时创建并在稍后执行。

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. 我已经使用Apache derby数据库跟随SLEEP()函数测试了这一点,该数据库在类TimeHandlingTest中调用java函数sleep。

CREATE FUNCTION SLEEP() RETURNS INTEGER LANGUAGE JAVA PARAMETER STYLE JAVA NO SQL EXTERNAL NAME 'com.derby.test.TimeHandlingTest.sleep'; CREATE FUNCTION SLEEP()返回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. 并从一个连接中创建了两个预处理语句,并从一个预处理语句中调用了Sleep()函数,并使用其他简单的sql select.Simple sql select花了几乎相同的时间(10s),其中第一个预处理语句正在休眠。这意味着一个连接对象不能用于一次执行多个准备好的声明。如果我错了,请纠正我。

You can't return the Connection to the pool if you plan on using the PreparedStatement . 如果您打算使用PreparedStatement则无法将Connection返回到池。

In other words: you can only use a PreparedStatement constructed from a Connection that you currently have. 换句话说:您只能使用从当前具有的Connection构造的PreparedStatement

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, eg PreparedStatement的值在于数据库本身为语句创建执行计划的能力,该语句可以重用于任意参数,因此本质上是通用的(当然,这需要您在语句中使用参数,例如

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. 另一方面,如果使用字符串连接将参数值粘贴到SQL代码中,则数据库将无法构建通用执行计划。 Thus it would make no difference if you use a PreparedStatement or Statement, eg 因此,如果您使用PreparedStatement或Statement,则没有任何区别,例如

PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
                               SET SALARY = 1200 WHERE ID = 3");

would not be able to use the advantage of PreparedStatements. 将无法使用PreparedStatements的优势。

Your question implies, that you want to reuse the PreparedStatement object, which is not necessary. 您的问题意味着,您希望重用PreparedStatement对象,这是不必要的。 Of course if you can use a PreparedStatement object to update multiple values etc. it is a more efficient use of ressources. 当然,如果您可以使用PreparedStatement对象来更新多个值等,则可以更有效地使用资源。 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. 然而,PreparedStatement的生命周期(或至少有用的生命周期)与Connection相关联,因此如果调用conn.close(),则PreparedStatement将变得无用。 Nevertheless most good drivers in a pooling situation reuse the same PreparedStatement objects again. 然而,池化情况下的大多数优秀驱动程序再次重用相同的PreparedStatement对象。 In short, don't cache the PreparedStatement independent of the connection. 简而言之,不要独立于连接缓存PreparedStatement。

Assuming that this is a multi-threaded application, Connection objects are typically associated with a single thread at any instant of time. 假设这是一个多线程应用程序, Connection对象通常在任何时刻与单个线程相关联。 Connection objects acquired by a thread are not returned to the pool until they are closed. 线程获取的Connection对象在关闭之前不会返回到池中。 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. 这既适用于逻辑连接包装器(通常由应用程序服务器管理的DataSource返回),也适用于应用程序,也适用于物理连接。 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. 如果您的应用程序需要处理并发用户而不会有任何麻烦,那么将在每个启动事务的线程中创建一个Connection对象,并且不会跨线程争用该对象。 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. 在引擎盖下,池中的不同物理连接将跨多个线程执行与准备好的语句关联的SQL查询,同样没有任何争用。

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. 此外,一些JDBC驱动程序现在支持Statement缓存,这减少了以这种方式使用它的开销。

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. 如果没有,请将准备好的语句传递给JDBC驱动程序,以便编译它。 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 . 但似乎这是一些J2EE服务器所做的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM