准备好的语句以及连接池

时间:2011-05-23 08:15:19

标签: java jdbc connection-pooling

我对准备声明的一般用法以及连接池有疑问。

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

如果在执行某些特定的预准备语句时,与准备好的语句关联的连接正忙于执行除了如何执行此必需语句之外的其他语句。此语句将等待连接获得释放或此语句将是给予执行中的偏好?

更新

我已经使用Apache derby数据库跟踪SLEEP()函数测试了这一点,该数据库在类TimeHandlingTest中调用java函数sleep。

CREATE FUNCTION SLEEP()返回INTEGER LANGUAGE JAVA PARAMETER STYLE JAVA NO SQL EXTERNAL NAME'com.derby.test.TimeHandlingTest.sleep';

从一个连接做了两个预备语句,从一个预准备语句中调用了Sleep()函数,用另一个简单的sql select.Simple sql select花了几乎相同的时间(10s),第一个准备好的语句正在睡觉。这意味着一个连接对象一次不能用于多个预准备语句的执行。如果我错了,请纠正我。

5 个答案:

答案 0 :(得分:8)

如果您打算使用Connection,则无法将PreparedStatement返回到池中。

换句话说:您只能使用由您当前拥有的PreparedStatement构建的Connection

答案 1 :(得分:4)

PreparedStatement的值在于数据库本身为可以为任意参数重用的语句创建执行计划的能力,因此 本质上是通用的(当然要求你在你的语句中使用参数,例如

PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
                               SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00);
pstmt.setInt(2, 110592);

另一方面,如果使用字符串连接将参数值粘贴到SQL代码中,则数据库将无法构建通用执行计划。因此,如果您使用PreparedStatement或Statement,那将没有任何区别,例如

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

无法使用PreparedStatements的优势。

您的问题意味着,您希望重用PreparedStatement对象,这是不必要的。当然,如果您可以使用PreparedStatement对象来更新多个值等,则可以更有效地使用资源。然而,PreparedStatement的生命周期(或至少有用的生命周期)与Connection相关联,因此如果调用conn.close(),则PreparedStatement将变得无用。然而,池化情况下的大多数优秀驱动程序再次重用相同的PreparedStatement对象。 简而言之,不要独立于连接缓存PreparedStatement。

答案 2 :(得分:2)

假设这是一个多线程应用程序,Connection对象通常在任何时刻与单个线程相关联。线程获取的Connection个对象在关闭之前不会返回到池中。这既适用于逻辑连接包装器(通常由应用程序服务器管理的DataSource返回),也适用于应用程序,也适用于物理连接。此外,物理连接可以在多个逻辑连接之间共享,只要它们是同一事务的一部分即可。

这意味着如果向您的应用程序返回逻辑连接句柄,则基础物理连接不必相同且正在争用(除非它是同一事务的一部分)。如果您的应用程序需要毫无困难地处理并发用户,那么将在每个启动事务的线程中创建一个Connection对象,并且不会跨线程争用此对象。在引擎盖下,池中的不同物理连接将跨多个线程执行与准备好的语句关联的SQL查询,同样没有任何争用。

答案 3 :(得分:1)

这听起来像是一种使用连接池的不寻常方式。即使连接在池中,它们也应该一次仅由一个线程使用。我倾向于创建准备好的语句并使用它非常接近创建点。此外,一些JDBC驱动程序现在支持Statement缓存,这减少了以这种方式使用它的开销。

答案 4 :(得分:0)

解决此问题的一种方法是维护连接映射到预准备语句的缓存。从池中获取连接时,检查它是否映射到要执行的预准备语句。如果没有,请将准备好的语句传递给JDBC驱动程序,以便编译它。然后将其映射到连接。这种方法的缺点是多个连接可能会获得相同预处理语句的副本。但似乎是this is what some J2EE servers do