statement和preparestatement

孤街浪徒 提交于 2019-11-27 17:39:20

一直都不是蛮清楚这二者的区别联系,今天就开一贴来详细的分析一下主要是从可读性,性能和效率上面来加以分析

  1. 在可读性方面来说:

//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 显得比较乱而且因为引号的原因比较容易出错,而preparedment则比较直观简洁

2.在性能方面:

每种数据库都会对预编译的语句提供最大的性能优化,因为有些编译语句会被重复调用,所以就把被数据库编译后的执行代码缓存起来,当下次调用只要是相同的预编译语句就不需要编译,只要将参数传入预编译的语句执行代码(相当于一个函数)中就会得到执行,因此大大提高了效率(对mysql来说没有多大区别但是对Oracle来说差距就非常明显

其次是Batch的使用

//多次执行preparestatement
PreparedStatement ps = conn.prepareStatement(  
   "INSERT into employees values (?, ?, ?)");  
  
for (n = 0; n < 100; n++) {  
  
  ps.setString(name[n]);  
  ps.setLong(id[n]);  
  ps.setInt(salary[n]);  
  ps.executeUpdate();  
} 

//使用Batch
PreparedStatement ps = conn.prepareStatement(  
   "INSERT into employees values (?, ?, ?)");  
  
for (n = 0; n < 100; n++) {  
  
  ps.setString(name[n]);  
  ps.setLong(id[n]);  
  ps.setInt(salary[n]);  
  ps.addBatch();  
}  
ps.executeBatch();

在例 1中, PreparedStatement被用来多次执行INSERT语句. 在这里, 执行了100次INSERT操作, 共有101次网络往返. 其中,1次往返是预储statement, 另外100次往返执行每个迭代. 在例2中, 当在100次INSERT操作中使用addBatch()方法时, 只有两次网络往返. 1次往返是预储statement, 另一次是执行batch命令. 虽然Batch命令会用到更多的数据库的CPU周期, 但是通过减少网络往返,性能得到提高. 记住, JDBC的性能最大的增进是减少JDBC驱动与数据库之间的网络通讯.
  注:Oracel 10G的JDBC Driver限制最大Batch size是16383条,如果addBatch超过这个限制,那么executeBatch时就会出现“无效的批值”(Invalid Batch Value) 异常。因此在如果使用的是Oracle10G,在此bug减少前,Batch size需要控制在一定的限度

对于不必重复使用和可以控制输入值得情况下statement在性能上还是比较好的

3.安全方面(防止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注入的机会)

参考文章:http://hanzhengyang0126.blog.163.com/blog/static/117503945201111294828507/

http://www.cnblogs.com/yezhenhan/archive/2011/04/21/2023195.html

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!