PreparedStatement和Statement的区别

在drp视频中,老师在数据库执行sql语句的时候多使用的是PreparedStatment,但是也提到了Statement。在视频中提到了一些区别,但是觉得不是很详细。

  视频中提到PreparedStatement的优点包括两个:

   1)会尽可能的提高性能

   2)提高安全性(防止SQL Injeciton)

  如争光说的二者相差一个单词Prepared,prepared的意思是准备好的。在处理SQL语句的时候PreparedStatement用于处理动态SQL语句,在执行前会有一个预编译过程,它是有时间开销的,虽然相对数据库的操作该时间开销可以忽略不计,但是Preparedstatement的预编译结果会被缓存,下次执行相同的sql语句是,数据库端不会再进行编译了。而直接用数据库的缓冲区,提高数据访问率。

一、在编写代码过程:

 Statement:

          stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");
   PreparedStatement:
   pstmt = con.prepareStatement("insert into tb_name(col1,col2,col2,col4) values (?,?,?,?)");
   pstmt.setString(1,var1);
   pstmt.setString(2,var2);
   pstmt.setString(3,var3);
   pstmt.setString(4,var4);
   pstmt.executeUpdate();
   可以看出来statement的代码写起来比较少但是给人的感觉就是乱,而且还容易出错;但是preparedStatement的代码虽然长一点,但是直接一个.就可以敲出来,给人的感觉是简单而且不容易出错。
   二、在性能方面:
   如果是大型的软件,需要保存在数据库中的数据量是非常大的,那么就要涉及到性能问题,无论是oracle还是SQL server都是这样的,每一种数据库都会近最大的努力对预编译语句提供最大的性能优化,因为有些编译语句有可能被重复调用。所以就有把被数据库编译后的执行代码缓存起来,当下次调用只要是相同的预编译语句就不需要编译。只要将参数直接传入编译过的语句执行代码中(相当于一个涵数)就会得到执行.这并不是说只有一个Connection中多次执行的预编译语句被缓存,而是对于整个DB中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次编译而可以直接执行.而statement的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配.比如:
insert into tb_name (col1,col2) values ('11','22');
insert into tb_name (col1,col2) values ('11','23');
即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存.
当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果.以保存有更多的空间存储新的预编译语句.这样能保持一种内存空间的平衡,不至于因为有过多的缓存而崩溃。
  三、安全性
  安全性是软件中最重要的一个问题,如果你的软件存在安全性问题那么你的软件也就无人问津了。而preparedStatement和statement就存在这样的问题。 
   在视频中讲解了一下sql注入的问题。  
    String sql = "select * from tb_name where name= '"+varname+"' and passwd='"+varpasswd+"'";
如果我们把[' or '1' = '1]作为varpasswd传入进来.用户名hzy,看看会成为什么?
select * from tb_name = 'hzy' and passwd = '' or '1' = '1';
因为'1'='1'肯定成立,所以可以任何通过验证.更有甚者:
把drop table tb_name;]作为varpasswd传入进来,则:
select * from tb_name = '随意' and passwd = '';drop table tb_name;有些数据库是不会让你成功的,但也有很多数据库就可以使这些语句得到执行.
而如果你使用预编译语句.你传入的任何内容就不会和原来的语句发生任何匹配的关系.只要全使用预编译语句,你就用不着对传入的数据做任何过虑.而如果使用普通的statement,有可能要对drop,;等做费尽心机的判断和过虑.
  PreparedStatement继承于Statement,通常的JDBC实现中PreparedStatement最终还是通过Statement的相关方法来执行SQL的(可以做少量优化),其最主要的优势在于,可以减少SQL的编译错误(在JDBC中就可以捕获部分异常而不是由数据库服务器执行时返回错误代码)、增加SQL安全性(减少SQL注入的机会)
    把PreparedStatement说的如此之好,并不是说statement就没有存在的意义了,对于不重复使用和可以控制输入值的情况下statement在性能上还是比较好的。每个东西都有它存在的必然道理,对与解决的问题的办法没有绝对的好也没有绝对的不好,米老师的话合适就好。

你可能感兴趣的:(sql,数据库,statement,drp,PREPARED)