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 --

原文地址:https://www.cnblogs.com/klory/p/10903086.html