一次有人问我为什么要使用JDBC中的PreparedStatement,我说可以“防止SQL注入”,其他的却不能说出个一二三,现在来看看其中的秘密
参考文章:
http://www.jb51.net/article/40138.htm
http://www.iteye.com/problems/32029
一、代码的可读性和可维护性
Statement 中 SQL 语句中需要 Java 中的变量,得进行字符串的运算,还需要考虑一些双引号、单引号的问题,参数变量越多,代码就越难看,而且会被单引号、双引号搞疯掉;而 PreparedStatement,则不需要这样,参数可以采用“?”占位符代替,接下来再进行参数的填充,虽然用PreparedStatement来代替Statement会使代码多出几行,但这样的代码无论从可读性还是可维护性上来说,都比直接使用Statement的代码高很多档次,并且符合面向对象的思想。
二、PreparedStatement尽最大可能提高性能
当你向数据库提交SQL语句后,数据库要对这条语句进行编译,例如语法分析、优化路径选择、分配资源等一系列操作,这是需要时间的。
当你向数据库插入10条记录时,如果使用常规做法,数据库需要编译10次,而使用PreparedStatement接口,数据库只需要编译一次,其他只是更改参数就可以了。
(1)statement每次执行sql语句,相关数据库都要执行sql语句的编译,preparedstatement是预编译的, preparedstatement支持批处理
(2)PreparedStatement对象的开销比Statement大,对于一次性操作并不会带来额外的好处。在对数据库只执行一次性存取的时侯,可用Statement对象进行处理,PreparedStatement对于批量处理可以大大提高效率。
三、最重要的一点是极大地提高了安全性
Statement 由于可能需要采取字符串与变量的拼接,很容易进行 SQL 注入攻击,而 PreparedStatement 由于是预编译,再填充参数的,不存在 SQL 注入问题。
所以说:选择PreparedStatement对象与否,在于相同句法的SQL语句是否执行了多次,而且两次之间的差别仅仅是变量的不同。
所谓的“预编译”到底是怎么回事呢?
预编译对象就是把一些格式固定的SQL编译后,存放在内存池中即数据库缓冲池,当我们再次执行相同的SQL语句时就不需要预编译的过程了,只需DBMS运行SQL语句。
Mysql支持预编译,只是默认没开启,Oracle里面除了查询结果集缓存外,还有SQL缓存。
语句缓存的好处:
(1)ORACLE执行SQL语句时,先将SQL语句的字串通过一个哈希算法得出一个哈希值,然后检查共享池中是否已存在这个哈希值,若有就用已缓存的执行计划来执行这个语句(CACHE HIT 缓存命中),若没有(CACHE MISS 缓存缺失)则需进行解析,解析需要完成下面的工作:
Ø 语法检查;
Ø 语义检查,看参考对象是否存在,类型是否正确;
Ø (如果是CBO优化模式)收集参考对象的统计;
Ø 检查用户的权限是否足够;
Ø 从许多可能的执行路径中选择一条作为执行计划;
Ø 生成语句的编译版本(P-CODE)。
(2)解析是一个昂贵的操作,因为过程中需要消耗许多资源;
(3)最大化CACHE HIT是调整共享池的目标
一个疑问贴:
http://www.iteye.com/problems/60861