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