繁体   English   中英

准备好的语句以及连接池

[英]Prepared Statements along with Connection Pooling

我有一个关于Prepared Statement的一般用法以及连接池的问题。

准备好的语句通常仅与一个连接相关联。在我们的应用程序中,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),其中第一个预处理语句正在休眠。这意味着一个连接对象不能用于一次执行多个准备好的声明。如果我错了,请纠正我。

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

换句话说:您只能使用从当前具有的Connection构造的PreparedStatement

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。

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

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

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

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

暂无
暂无

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

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