Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/346.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 编译后的语句是存储在对象中还是一般情况下?_Java_Jdbc - Fatal编程技术网

Java 编译后的语句是存储在对象中还是一般情况下?

Java 编译后的语句是存储在对象中还是一般情况下?,java,jdbc,Java,Jdbc,我知道,第一次使用jdbc时,jdbc会将编译好的预处理语句保存在某个地方,以便下次可以更有效地访问它 现在,假设我有这种情况: public class MyDao{ public void doQuery(){ try(PreparedStatement stmt = connection.prepareStatement(MY_STMT)){ } } } 以下两个代码段都将在内存中保留已编译的prepared

我知道,第一次使用jdbc时,jdbc会将编译好的预处理语句保存在某个地方,以便下次可以更有效地访问它

现在,假设我有这种情况:

public class MyDao{
       public void doQuery(){
           try(PreparedStatement stmt = connection.prepareStatement(MY_STMT)){

            }
       }

 }
以下两个代码段都将在内存中保留已编译的prepared语句

片段1:

MyDao dao = new MyDao();
dao.doQuery(); //first one, expensive
dao.doQuery(); //second one, less expensive as it has been already compiled
片段2:

MyDao dao = new MyDao();
dao.doQuery(); //first one, expensive
MyDao dao2 = new MyDao();
dao2.doQuery(); //will it be expensive or less expensive?
我担心,通过创建一个新的dao对象,jvm会将准备好的语句视为一个新语句,因此不会编译它

如果不是这样,jvm是否会“忘记”已编译语句并再次编译它


谢谢

你说得对,它将被再次编译。只有在多次实际使用语句本身时(即多次对其调用
executeQuery
),PreparedStatements才会被重用


不过,我不会太担心编写该声明的成本。如果查询花费的时间超过几毫秒,编译的成本将是微不足道的。编译语句的开销只有在每秒执行1000次操作时才会变得明显。

执行基准测试。这是确定性能差异的最佳方法。不一定总是在服务器端重新编译语句。根据您的RDBMS,它可能会缓存以前编译的语句。为了最大限度地提高缓存命中概率,请始终提交完全相同的参数化SQL文本,并在相同的连接上执行此操作。

预处理语句重用的最基本场景是代码保持
PreparedStatement
打开并重用该预处理语句。您的示例代码不符合此条件,因为您关闭了准备好的语句。另一方面,由于潜在的并发性问题(例如,如果多个线程使用同一个DAO,您可能会执行多个线程的值的奇怪组合,等等),尝试为多个方法调用打开一个准备好的语句通常不是一个好的计划

一些JDBC驱动程序在内部有一个准备好的语句(可选)缓存(池)以供重用,但只有在尝试在同一物理连接上再次准备相同的语句文本时,才会发生重用。检查驱动程序的文档


在另一个层次上,数据库系统可能会缓存准备好的语句的执行计划,并且如果再次准备相同的语句文本(即使是不同的连接),它可以(将)重用该执行计划。

我非常确定JDBC本身并没有指定将编译好的准备好的语句缓存在客户机上(Java)一边当然,有些数据库引擎会在服务器端缓存执行计划,有些ORM(或类似的)可能会尝试对结果进行客户端缓存,但似乎不太可能对已编译语句进行客户端缓存(在任何情况下,任何此类尝试都将严重依赖于JDBC驱动程序的实现)@GordThompson JDBC规范确实在第11.6节(JDBC 4.2)中提到了一些关于池(缓存)准备语句的内容,但是驱动程序缓存准备语句是否是特定于实现的。即使这样,池也会绑定到连接上。JDBC是否仍然可以发送参数化查询,而不需要在驱动程序/客户机中存储准备好的语句?使用ADO.NET,只需发送一个带有绑定参数的查询,数据库通过查询字符串记住该查询,从而重用预编译的计划。这适用于SQL Server(过程sp_executesql)和Oracle(内部使用executeimmediate)。JDBC没有类似的方式发送查询,以便存储、记忆和被数据库重用吗?@MarkRotteveel感谢您的澄清。在写评论时,我可能过于关注“已编译”的概念以及JDBC驱动程序可能在本地缓存“已编译”查询的版本(或特定于db的执行计划)的含义。毫无疑问,JDBC驱动程序可以维护客户端
PreparedStatement
对象和服务器端“编译查询”(例如,类似于SQL server的
sp_prepare
的结果)之间的关联,但这取决于驱动程序的实现。@ErikHart这就是
PreparedStatement
的作用,就像ado.net中的
命令
对象一样。这取决于驱动程序实现是否真正准备了服务器端的语句。ado.net唯一的真正区别在于,您不能将不同的语句分配给
PreparedStatement
的实例。