`

Statement 和 PreparedStatement的见解【原创+转摘】

阅读更多

用PreparedStatement 去批量调用。是执行同一条sql语句,但是传入不同的参数。数据库在执行每条sql语句的时候都是需要先编译再执行的。如果每次都传入一条完整的sql,那么数据库进行处理的时候对每条sql语句都需要进行编译、执行、返回结果。如果用preparedstatement 可以只编译一次sql语句,然后通过传入不同的参数执行sql语句。这样效率就搞跟多。反正你记住,在这种相同的sql,很多不同的值去替换的时候要用批处理。预编译处理方式。

 

下面是转载的:

PreparedStatement的最大的优点就是可以动态设置参数,然后其缺点也来源于此,在执行SQL语句出错的时候,我们就没有办法看到完整的 SQL语句,甚至也看不到设置的参数,这非常不便于调试。比如说,执行一个非常长的sql语句的时候,报错说插入的值超出范围,大部分JDBC驱动都不会报告是哪个字段出了问题,难道只能执行SQL语句之前将所有参数值手工打印出来吗?而程序调试通过后,这些垃圾代码又都需要清除掉。当一个程序处于不断的调试过程中,这将是极其痛苦的。


PreparedStatement可以避免一些编码的麻烦,如单引号的问题。
完全可以用PreparedStatement来代替Statement


在JDBC应用中,如果你已经是稍有水平开发者,你就应该始终以PreparedStatement代替Statement.也就是说,在任何时候都不要使用Statement.
基于以下的原因:
一.代码的可读性和可维护性.
虽然用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说.都比直接用Statement的代码高很多档次:
  
stmt.executeUpdate("insert   into   tb_name   (col1,col2,col2,col4)   values   ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");
  
perstmt   =   con.prepareStatement("insert   into   tb_name   (col1,col2,col2,col4)   values   (?,?,?,?)");
perstmt.setString(1,var1);
perstmt.setString(2,var2);
perstmt.setString(3,var3);
perstmt.setString(4,var4);
perstmt.executeUpdate();
  
不用我多说,对于第一种方法.别说其他人去读你的代码,就是你自己过一段时间再去读,都会觉得伤心.
  
二.PreparedStatement尽最大可能提高性能.
每一种数据库都会尽最大努力对预编译语句提供最大的性能优化.因为预编译语句有可能被重复调用.所以语句在被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个涵数)就会得到执行.这并不是说只有一个 Connection中多次执行的预编译语句被缓存,而是对于整个DB中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次编译而可以直接执行.而statement的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配.比如:
insert   into   tb_name   (col1,col2)   values   ('11','22');
insert   into   tb_name   (col1,col2)   values   ('11','23');
即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存.这样每执行一次都要对传入的语句编译一次.
  
当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果.以保存有更多的空间存储新的预编译语句.
  
三.最重要的一点是极大地提高了安全性.
  
即使到目前为止,仍有一些人连基本的恶义SQL语法都不知道.
String   sql   =   "select   *   from   tb_name   where   name=   '"+varname+"'   and   passwd='"+varpasswd+"'";
如果我们把['   or   '1'   =   '1]作为varpasswd传入进来.用户名随意,看看会成为什么?
  
select   *   from   tb_name   =   '随意'   and   passwd   =   ''   or   '1'   =   '1';
因为'1'='1'肯定成立,所以可以任何通过验证.更有甚者:
把[';drop   table   tb_name;]作为varpasswd传入进来,则:
select   *   from   tb_name   =   '随意'   and   passwd   =   '';drop   table   tb_name;有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行.
  
而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.(前提是数据库本身支持预编译,但上前可能没有什么服务端数据库不支持编译了,只有少数的桌面数据库,就是直接文件访问的那些)只要全使用预编译语句,你就用不着对传入的数据做任何过虑.而如果使用普通的 statement,有可能要对drop,;等做费尽心机的判断和过虑.

================================================

以Oracle为例吧
Statement为一条Sql语句生成执行计划,
如果要执行两条sql语句
select colume from table where colume=1;
select colume from table where colume=2;
会生成两个执行计划
一千个查询就生成一千个执行计划!

PreparedStatement用于使用绑定变量重用执行计划
select colume from table where colume=:x;
通过set不同数据只需要生成一次执行计划,可以重用

是否使用绑定变量对系统影响非常大,生成执行计划极为消耗资源
两种实现 速度差距可能成百上千倍

1.PreparedStatement是预编译的,对于批量处理可以大大提高效率. 也叫JDBC存储过程
2.使用 Statement 对象。在对数据库只执行一次性存取的时侯,用 Statement 对象进行处理。PreparedStatement 对象的开销比Statement大,对于一次性操作并不会带来额外的好处。
3.statement每次执行sql语句,相关数据库都要执行sql语句的编译,preparedstatement是预编译得, preparedstatement支持批处理
4.
Code Fragment 1:

String updateString = "UPDATE COFFEES SET SALES = 75 " + "WHERE COF_NAME LIKE ′Colombian′";
stmt.executeUpdate(updateString);

Code Fragment 2:

PreparedStatement updateSales = con.prepareStatement("UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
updateSales.setInt(1, 75);
updateSales.setString(2, "Colombian");
updateSales.executeUpdate();

片断2和片断1的区别在于,后者使用了PreparedStatement对象,而前者是普通的Statement对象。PreparedStatement对象不仅包含了SQL语句,而且大多数情况下这个语句已经被预编译过,因而当其执行时,只需DBMS运行SQL语句,而不必先编译。当你需要执行Statement对象多次的时候,PreparedStatement对象将会大大降低运行时间,当然也加快了访问数据库的速度。
这种转换也给你带来很大的便利,不必重复SQL语句的句法,而只需更改其中变量的值,便可重新执行SQL语句。选择PreparedStatement对象与否,在于相同句法的SQL语句是否执行了多次,而且两次之间的差别仅仅是变量的不同。如果仅仅执行了一次的话,它应该和普通的对象毫无差异,体现不出它预编译的优越性。
5.执行许多SQL语句的JDBC程序产生大量的Statement和PreparedStatement对象。通常认为PreparedStatement对象比Statement对象更有效,特别是如果带有不同参数的同一SQL语句被多次执行的时候。PreparedStatement对象允许数据库预编译SQL语句,这样在随后的运行中可以节省时间并增加代码的可读性。

然而,在Oracle环境中,开发人员实际上有更大的灵活性。当使用Statement或PreparedStatement对象时,Oracle数据库会缓存SQL语句以便以后使用。在一些情况下,由于驱动器自身需要额外的处理和在Java应用程序和Oracle服务器间增加的网络活动,执行PreparedStatement对象实际上会花更长的时间。

然而,除了缓冲的问题之外,至少还有一个更好的原因使我们在企业应用程序中更喜欢使用PreparedStatement对象,那就是安全性。传递给PreparedStatement对象的参数可以被强制进行类型转换,使开发人员可以确保在插入或查询数据时与底层的数据库格式匹配。

当处理公共Web站点上的用户传来的数据的时候,安全性的问题就变得极为重要。传递给PreparedStatement的字符串参数会自动被驱动器忽略。最简单的情况下,这就意味着当你的程序试着将字符串“D'Angelo”插入到VARCHAR2中时,该语句将不会识别第一个“,”,从而导致悲惨的失败。几乎很少有必要创建你自己的字符串忽略代码。

在Web环境中,有恶意的用户会利用那些设计不完善的、不能正确处理字符串的应用程序。特别是在公共Web站点上,在没有首先通过PreparedStatement对象处理的情况下,所有的用户输入都不应该传递给SQL语句。此外,在用户有机会修改SQL语句的地方,如HTML的隐藏区域或一个查询字符串上,SQL语句都不应该被显示出来。
在执行SQL命令时,我们有二种选择:可以使用PreparedStatement对象,也可以使用Statement对象。无论多少次地使用同一个SQL命令,PreparedStatement都只对它解析和编译一次。当使用Statement对象时,每次执行一个SQL命令时,都会对它进行解析和编译。


第一:

prepareStatement会先初始化SQL,先把这个SQL提交到数据库中进行预处理,多次使用可提高效率。
createStatement不会初始化,没有预处理,没次都是从0开始执行SQL

第二:

prepareStatement可以替换变量
在SQL语句中可以包含?,可以用ps=conn.prepareStatement("select * from Cust where ID=?");
int sid=1001;
ps.setInt(1, sid);
rs = ps.executeQuery();
可以把?替换成变量。
而Statement只能用
int sid=1001;
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from Cust where ID="+sid);
来实现。

第三:

prepareStatement会先初始化SQL,先把这个SQL提交到数据库中进行预处理,多次使用可提高效率。
createStatement不会初始化,没有预处理,没次都是从0开始执行SQL

分享到:
评论

相关推荐

    Statement和PreparedStatement之间的区别

    Statement和PreparedStatement之间的区别 Statement和PreparedStatement是JDBC中的两种不同的语句对象,用于执行数据库操作。虽然它们都可以执行SQL语句,但是它们之间存在着很大的区别。 首先, Statement对象...

    java中PreparedStatement和Statement的区别

    Java 中 PreparedStatement 和 Statement 的区别 Java 中的 PreparedStatement 和 Statement 都是用于执行 SQL 语句的接口,但是它们之间存在一些关键的区别。 首先,从数据库执行 SQL 语句的角度来看,使用 ...

    PreparedStatement和Statement

    在Java编程中,数据库操作是常见任务之一,而`PreparedStatement`和`Statement`是Java JDBC(Java Database Connectivity)中用于执行SQL语句的两种主要接口。它们都是`java.sql`包下的类,用来与数据库进行交互,但...

    statement和prepared区别

    其中,Statement和PreparedStatement是两种常用的SQL语句执行接口。在理解和掌握它们之间的区别之前,我们需要首先了解JDBC对于数据库操作的基本概念。 JDBC的主要作用是提供了一套标准的API,使得Java程序能够连接...

    prepareStatement和Statement的区别

    prepareStatement和Statement的区别 prepareStatement和Statement是 Java 中两个常用的数据库操作接口,它们都可以用来执行 SQL 语句,但是它们之间有着明显的区别。 首先,从创建时的区别开始,Statement 需要...

    详解Java的JDBC中Statement与PreparedStatement对象

    在Java的JDBC(Java Database Connectivity)中,与数据库交互的核心接口是Statement和PreparedStatement。这两个接口都是用于执行SQL语句的,但它们在特性和效率上有所不同。 Statement接口是最基本的SQL执行方式...

    connection 和 preparedstatement 的关闭问题

    正确地选择`Statement`和`PreparedStatement`以及适时地关闭它们对于保证应用程序的性能和稳定性至关重要。理解它们之间的区别,并根据实际需求选择合适的方法,能够显著提升应用的质量。同时,合理管理`Connection`...

    软件测试中使用JDBC插入大量数据的性能测试

    jdbc数据软件测试中使用JDBC插入大量数据的性能测试使用jdbc向数据库插入100000条记录,分别使用statement,PreparedStatement,及PreparedStatement+批处理3种方式进行测试:1、使用statement插入100000条记录...

    关于PreparedStatement插入Date类型值的方法.txt

    `PreparedStatement`是`Statement`接口的子接口,用于预编译SQL语句,并可以重复执行这些预编译过的SQL语句。这不仅能够提高应用程序的性能,还能提高安全性,因为它支持参数化查询,避免了SQL注入的风险。 #### 二...

    如何获得PreparedStatement最终执行的sql语句

    一种可能的方法是通过日志配置,例如,启用MySQL的`Statement`和`PreparedStatement`日志,这样在执行时会打印出详细的SQL语句。 另外,开发工具如IntelliJ IDEA、Eclipse等,或者数据库管理工具如MySQL Workbench...

    PreparedStatement详细用法

    在这个例子中,首先定义了一个包含占位符的SQL语句,接着通过`connection`对象的`prepareStatement`方法创建`PreparedStatement`实例,然后通过`setInt`和`setString`方法设置参数值,最后调用`executeQuery`方法...

    PreparedStatement 详细用法

    在Java编程语言中,`PreparedStatement`是`java.sql`包中的一个接口,它继承自`Statement`类,并提供了预编译SQL语句的功能。预编译SQL语句的主要优势在于提高了执行效率和安全性。尤其在处理动态查询或频繁执行相同...

    JDBC基础教程之PreparedStatement.doc

    `PreparedStatement`是Java数据库连接(JDBC)API中的一种重要接口,它继承自`Statement`接口,并在其基础上进行了扩展和优化。`PreparedStatement`的主要特点在于它可以预先编译SQL语句,并允许用户在执行前动态地...

    34.jdbc中preparedStatement比Statement的好处.avi

    jdbc中preparedStatement比Statement的好处

    PreparedStatement

    jdbc2.0版 PreparedStatement接口的用法

    练习3:使用PreparedStatement插入宠物信息.zip

    在Java编程中,PreparedStatement是Java SQL API中的一个接口,它是Statement接口的子接口。这个练习主要涉及如何使用PreparedStatement来插入宠物信息到数据库中。PreparedStatement的主要优势在于它的预编译能力和...

    数据库-数据库编码解决方案

    首先我们设计Connection接口的代理类_Connection,这个代理类接管了Connection接口中所有可能获取到Statement或者PreparedStatement接口实例的方法,例如:prepareStatement和createStatement。改变这两个方法使之...

    怎样实现关闭connection时自动关闭Statement和ResultSet (下篇)

    此外,还可以考虑使用PreparedStatement和CallableStatement,它们在性能和安全性上优于Statement。PreparedStatement允许预编译SQL语句,减少解析开销,同时能有效防止SQL注入攻击。CallableStatement则用于调用...

    【性能】JDBC PreparedStatement和连接池PreparedStatement Cache学习记录

    在Java的数据库编程中,`JDBC PreparedStatement`和连接池中的`PreparedStatement Cache`是两个非常重要的概念,它们对于提升应用程序的性能和效率有着显著的作用。本文将深入探讨这两个主题,并结合Oracle数据库的...

Global site tag (gtag.js) - Google Analytics