关于PreparedStatement与Statement的比较,网络上已经有许多文章告诉我们要使用PreparedStatement来代替Statement。大致的原因是:
1、预编译语句有可能被重复调用.所以语句在被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中(相当于一个函数)就会得到执行.这并不是说只有一个Connection中多次执行的预编译语句被缓存,而是对于整个DB中,只要预编译的语句语法和缓存中匹配.那么在任何时候就可以不需要再次编译而可以直接执行。
2、安全性,使用PreparetStatement可防止SQL语句注入(injection sql)。
注入式SQL攻击,举个简单例子说明:
logName = (String)request.getParameter("txt_LogName");
logPwd = (String)request.getParameter("txt_LogPwd");
sql = "select useName,usePwd from userTable where useName='"+logName+"' and usePwd='"+logPwd+"'";
conn = DBConn.getConn();
stmt = conn.createStatement();
rs = stmt.executeQuery(sql);
这样的标准式代码却存在严重的安全性能。如果我们的登录界面的用户框或是密码框加入[' or '1'='1](不包括[],下同)那么上述的sql就变成了。
select useName,usePwd from userTable where useName='user ' and usePwd='test' or '1'='1'
这样的语句在Statement中是肯定成功执行的,后果是不经认证就登录了。
当然hacker从来不会这样就罢休。如果改成执行这样的,在用户框或密码框加入
[test';insert into userTable(useName,usePwd) values('hacker','123');--]
这样的话,就增加了一个永久是帐户了。
更破坏性的是[test'; drop talbe userTable;--],后果想想知道了。这也是为什么大力推荐使用PreparedStatement的主要原因。
但凡事都有度,正因为PreparedStatement是预编译的,所以在第一次执行时要比Statement慢。而且象Oracle本身就是强大的数据库优化策略,也就是说在执行Statement时,也会优化。例insert into table value('1','2'),数据库会优化成insert into table value(?,?)。这时的Statement跟PreparedStatement就是一样的了。当然有个例外,不是所有的数据库会有此优化策略。
总结一下,就是批量写记录时,绝对使用PreparedStatement,如果是多参数动态查询,一般使用Statement。当然,出于安全方面,使用PreparedStatement比较好。