Java 准备好的语句以及连接池

Java 准备好的语句以及连接池,java,jdbc,connection-pooling,Java,Jdbc,Connection Pooling,我有一个关于预处理语句和连接池的一般用法的问题 PreparedStatement通常只绑定到一个连接。在我们的应用程序中,PreparedStatement在启动时创建,并在稍后执行 如果在执行某些特定的预处理语句时,与预处理语句关联的连接正忙于执行其他语句,而不是执行此必需语句的方式。此语句是否将等待连接释放,或者在执行时将优先考虑此语句 更新 我已经用ApacheDerby数据库跟踪了SLEEP()函数,该数据库在类TimeHandlingTest中调用java函数SLEEP CREATE

我有一个关于预处理语句和连接池的一般用法的问题

PreparedStatement通常只绑定到一个连接。在我们的应用程序中,PreparedStatement在启动时创建,并在稍后执行

如果在执行某些特定的预处理语句时,与预处理语句关联的连接正忙于执行其他语句,而不是执行此必需语句的方式。此语句是否将等待连接释放,或者在执行时将优先考虑此语句

更新

我已经用ApacheDerby数据库跟踪了SLEEP()函数,该数据库在类TimeHandlingTest中调用java函数SLEEP

CREATE FUNCTION SLEEP()返回整数语言JAVA参数样式JAVA NO SQL外部名称'com.derby.test.TimeHandlingTest.SLEEP'


并从一个连接中生成了两个准备好的语句,从一个准备好的语句调用了Sleep()函数,然后用另一个调用了简单的sql选择第一个准备好的语句正在休眠。这意味着一个连接对象一次不能由多个准备好的语句执行。如果我错了,请纠正我。

如果您计划使用
PreparedStatement
,则无法将
连接返回池


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

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

PreparedStatement的价值在于数据库本身能够为语句创建一个执行计划,该计划可以对任意参数重复使用,因此是安全的 本质上是泛型的(当然,这要求您在声明中使用参数,例如

PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
                               SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00);
pstmt.setInt(2, 110592);
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
                               SET SALARY = 1200 WHERE ID = 3");
另一方面,如果您使用字符串连接将参数值粘贴到SQL代码中,则数据库将无法构建通用执行计划。因此,如果您使用PreparedStatement或语句(例如

PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
                               SET SALARY = ? WHERE ID = ?");
pstmt.setBigDecimal(1, 153833.00);
pstmt.setInt(2, 110592);
PreparedStatement pstmt = con.prepareStatement("UPDATE EMPLOYEES
                               SET SALARY = 1200 WHERE ID = 3");
无法利用准备好的报表的优势

您的问题表明,您希望重用PreparedStatement对象,这是不必要的。当然,如果您可以使用PreparedStatement对象来更新多个值等,这将是对资源的更有效的使用。尽管如此,它的使用寿命(或至少是有效的使用寿命)PreparedStatement的属性与连接绑定,因此如果调用conn.close(),PreparedStatement将变得无用。不过,池中的大多数优秀驱动程序会再次重用相同的PreparedStatement对象。
简而言之,不要缓存独立于连接的PreparedStatement。

一种解决方法是维护一个缓存,其中连接映射到prepared语句。当您从池中获取连接时,请检查它是否映射到要执行的prepared语句。如果没有,请将prepared语句传递给JDBC驱动程序,以便这种方法的缺点是,多个连接可能会得到同一条准备好的语句的副本。但似乎。

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


这意味着,如果将逻辑连接句柄返回到应用程序,则底层物理连接不必相同,也不必被争用(除非它是同一事务的一部分)。如果希望您的应用程序能够轻松处理并发用户,则会在启动事务的每个线程中创建一个
连接
对象,并且不会跨线程争用此对象。在后台,池中的不同物理连接将执行与预处理关联的SQL查询ared语句,跨多个线程,同样没有任何争用。

您的代码是否在应用程序服务器上运行?当您使用数据源而不是DriverManager来获取连接时,答案会有所不同。@Vinet:我们的应用程序是一个简单的java应用程序,不在应用程序服务器上运行。我们从驱动程序管理器。这似乎不是一个合理的解决方案,因为我的应用程序可能需要连接作为准备语句。这不是一个解决方案,这是一个要求!如果你不遵循这一点,那么你迟早会遇到麻烦。谢谢你的回答,但我的主要问题是,如果连接与我的prepared语句正在忙于运行任何其他prepare语句,以了解我的prepare语句将如何运行。我们能否在一个时间点通过一个连接运行多个prepared语句?\n感谢您的回答。据我所知,prepared语句是根据物理连接而不是逻辑连接缓存的。如果sical连接在执行语句时已经很忙,那么我们可以在同一物理连接上运行另一个准备好的语句,还是需要使用