zoukankan      html  css  js  c++  java
  • preparestatement和statement的区别&&简单的SQL注入

    在JDBC应用中,强烈建议使用PreparedStatement代替Statement.也就是说,在任何时候都不要使用Statement.

    原因如下:

    一.代码的可读性和可维护性.

    var1 = "kia";
    var2 = "10086"
    statment需要动态拼接SQL语句
    statment.executeUpdate("insert sysuser (uname,uphone) values ('"+var1+"','"+var2+"')");
    perparedstatment需要使用 ? 占位符
    perparedstatment=conn.prepareStatement("insert sysuser (uname,uphone) values (?,?) ");
    perparedstatment.setString(1,var1);
    perparedstatment.setString(2,var2);
    perstmt.executeUpdate();
    

     

    PreparedStatement需要编译后的执行时再传入参数
    ==>  Preparing: insert sysuser (uname,uphone) values (?,?) 
    ==> Parameters: kia(String), 10086(String)
    Statement需要编译时直接传入参数
    ==>  Preparing: insert sysuser (uname,uphone) values ('kia','10086') 
    ==> Parameters: 
    

    虽然用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说.都比直接用Statement的代码高

    二.PreparedStatement尽最大可能提高性能.

    每一种数据库都会尽最大努力对预编译语句提供最大的性能优化.因为预编译语句有可能被重复调用.所以语句在被JDBC的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个涵数)就会得到执行.这并不是说只有一个Connection中多次执行的预编译语句被缓存,而是对于整个JDBC中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次编译而可以直接执行.

    而statement的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配.比如:
      insertintotb_name(col1,col2)values('11','22');
      insertintotb_name(col1,col2)values('11','23');
    即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存.
    当然并不是所有预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果.以保存有更多的空间存储新的预编译语句.

    每一种数据库都会尽最大努力对预编译语句提供最大的性能优化.因为预编译语句有可能被重复调用.所以语句在被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个涵数)就会得到执行.这并不是说只有一个Connection中多次执行的预编译语句被缓存,而是对于整个DB中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次编译而可以直接执行.而statement的语句中,即使是相同一操作,而由于每次操作的数据不同所以使整个语句相匹配的机会极小,几乎不太可能匹配.比如:
      insertintotb_name(col1,col2)values('11','22');
      insertintotb_name(col1,col2)values('11','23');
      即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存.
      当然并不是所有预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候不再缓存已有的预编译结果.以保存有更多的空间存储新的预编译语句.

    三.最重要的一点是极大地提高了安全性.可以预防SQL注入

    SQL中单行注释 : -- 

    例如:

    正常的delete语句 :delete from sysuser WHERE uid = '2' 

    恶意delete语句 : delete from sysuser WHERE uid = ' 前端传入的值 '

    前端传入的值为:2 ' OR 1 = 1 -- ;此时的SQL语句为  delete from sysuser WHERE uid = ' 2 ' OR 1 = 1 --  '

    由于--单行注释的存在,--  '  被注释掉了;真正执行的SQL语句为 delete from sysuser WHERE uid = ' 2 ' OR 1 = 1,会将所有的数据库表中的数据全部删除

    而使用预编译语句,最多最后写入数据库的值变为  2 ' OR 1 = 1 --

  • 相关阅读:
    java:maven(maven-ssm(聚合,分包开发))
    java:Maven(Maven_ssm)
    java:Mybatis框架3(二级缓存,延时和积极加载,SSI(Ibatis)集成,SSM集成)
    java:LeakFilling (Mybatis)
    java:Mybatis框架2(基于mapper接口的开发,多种查询,复合类型查询,resultMap定义,多表联查,sql片段)
    java:Mybatis框架1(基本配置,log4j,Junit4(单元测试))
    java:Springmvc框架3(Validator)
    java:Springmvc框架2(Ajax,Json,Interceptor,Upload,Exception)
    WebLogic XMLDecoder反序列化漏洞复现
    Struts2-052 漏洞复现
  • 原文地址:https://www.cnblogs.com/klory/p/10903086.html
Copyright © 2011-2022 走看看