转载请注明原文地址: http://www.cnblogs.com/ygj0930/p/5876951.htmlhtml
在JDBC编程中,经常使用Statement、PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询, PreparedStatement 用于执行参数化查询,而 CallableStatement则是用于存储过程。java
一、Statement
该对象用于执行静态的 SQL 语句,而且返回执行结果。 此处的SQL语句必须是完整的,有明确的数据指示。查的是哪条记录?改的是哪条记录?都要指示清楚。
经过调用 Connection 对象的 createStatement 方法建立该对象
查询:ResultSet excuteQuery(String sql)——返回查询结果的封装对象ResultSet. 用next()遍历结果集,getXX()获取记录数据。
修改、删除、增长:int excuteUpdate(String sql)——返回影响的数据表记录数. mysql
二、PreparedStatement
SQL 语句被预编译并存储在 PreparedStatement 对象中。而后可使用此对象屡次高效地执行该语句。
能够经过调用 Connection 对象的 preparedStatement() 方法获取 PreparedStatement 对象
PreparedStatement 对象所执行的 SQL 语句中,参数用问号(?)来表示,调用 PreparedStatement 对象的 setXXX() 方法来设置这些参数. setXXX() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1 开始),第二个是设置的 SQL 语句中的参数的值,注意用setXXX方式设置时,须要与数据库中的字段类型对应,例如mysql中字段为varchar,就须要使用setString方法,若是为Date类型,就须要使用setDate方法来设置具体sql的参数。sql
简单来讲就是,预编译的SQL语句不是有具体数值的语句,而是用(?)来代替具体数据,而后在执行的时候再调用setXX()方法把具体的数据传入。同时,这个语句只在第一次执行的时候编译一次,而后保存在缓存中。以后执行时,只需从缓存中抽取编译过了的代码以及新传进来的具体数据,便可得到完整的sql命令。这样一来就省下了后面每次执行时语句的编译时间。数据库
使用预编译分4步走:编程
1:定义预编译的sql语句,其中待填入的参数用 ? 占位。注意,?无关类型,不须要加分号之类。其具体数据类型在下面setXX()时决定。缓存
2:建立预编译Statement,并把sql语句传入。此时sql语句已与此preparedStatement绑定。因此第4步执行语句时无需再把sql语句做为参数传入execute()。性能
3:填入具体参数。经过setXX(问号下标,数值)来为sql语句填入具体数据。注意:问号下标从1开始,setXX与数值类型有关,字符串就是setString(index,str).优化
4:执行预处理对象。主要有:网站
boolean |
execute() 在此 PreparedStatement 对象中执行 SQL 语句,该语句能够是任何种类的 SQL 语句。 |
ResultSet |
executeQuery() 在此 PreparedStatement 对象中执行 SQL 查询,并返回该查询生成的 ResultSet 对象。 |
int |
executeUpdate() 在此 PreparedStatement 对象中执行 SQL 语句,该语句必须是一个 SQL 数据操做语言(Data Manipulation Language,DML)语句,好比 INSERT 、UPDATE 或 DELETE 语句;或者是无返回内容的 SQL 语句,好比 DDL 语句。 |
注意,前面建立preparedstatement时已经把sql语句传入了,此时执行不需再把sql语句传入,这是与通常statement执行sql语句所不一样之处。
好比:
String sql="select Sname from stu where Sno=?"
PreparedStatement prestmt = conn.prepareStatement(sql
);
prestmt.setString(
1
,sno);
prestmt.executeQuery();
使用预编译的好处:
1:PreparedStatement比 Statement 更快
使用 PreparedStatement 最重要的一点好处是它拥有更佳的性能优点,SQL语句会预编译在数据库系统中。执行计划一样会被缓存起来,它容许数据库作参数化查询。使用预处理语句比普通的查询更快,由于它作的工做更少(数据库对SQL语句的分析,编译,优化已经在第一次查询前完成了)。
2:PreparedStatement能够防止SQL注入式攻击
SQL 注入攻击:SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令,从而利用系统的 SQL 引擎完成恶意行为的作法。
好比:某个网站的登陆验证SQL查询代码为:
1
|
strSQL =
"SELECT * FROM users WHERE name = '"
+ userName +
"' and pw = '"
+ passWord +
"';"
|
恶意填入:
1
2
|
userName =
"1' OR '1'='1"
;
passWord =
"1' OR '1'='1"
;
|
那么最终SQL语句变成了:
1
|
strSQL =
"SELECT * FROM users WHERE name = '1' OR '1'='1' and pw = '1' OR '1'='1';"
|
由于WHERE条件恒为真,这就至关于执行:
1
|
strSQL =
"SELECT * FROM users;"
|
所以能够达到无帐号密码亦可登陆网站。
若是恶意用户要是更坏一点,SQL语句变成:
1
|
strSQL =
"SELECT * FROM users WHERE name = 'any_value' and pw = ''; DROP TABLE users"
|
这样一来,虽然没有登陆,可是数据表都被删除了。
使用PreparedStatement的参数化的查询能够阻止大部分的SQL注入。在使用参数化查询的状况下,数据库系统不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,所以就算参数中含有破坏性的指令,也不会被数据库所运行。由于对于参数化查询来讲,查询SQL语句的格式是已经规定好了的,须要查的数据也设置好了,缺的只是具体的那几个数据而已。因此用户能提供的只是数据,并且只能按需提供,没法更进一步作出影响数据库的其余举动来。
参考资料:
http://www.importnew.com/5006.html