execute
boolean execute()
throws SQLException在此
PreparedStatement
对象中执行 SQL 语句,该语句可以是任何种类的 SQL 语句。一些预处理过的语句返回多个结果,execute
方法处理这些复杂的语句,executeQuery
和executeUpdate
处理形式更简单的语句。
execute
方法返回一个boolean
值,指示第一个结果的形式。必须调用getResultSet
或getUpdateCount
方法获取该结果,必须调用getMoreResults
获取任何后续结果。
返回:
如果第一个结果是
ResultSet
对象,则返回true
;如果第一个结果是更新计数或者没有结果,则返回false
抛出:
SQLException
- 如果发生数据库访问错误;在关闭的PreparedStatement
上调用此方法,或者为此方法提供了参数
executeQuery
ResultSet executeQuery() throws SQLException
在此
PreparedStatement
对象中执行 SQL 查询,并返回该查询生成的ResultSet
对象。
返回:
包含该查询生成的数据的
ResultSet
对象;不会返回null
抛出:
SQLException
- 如果发生数据库访问错误,在关闭的PreparedStatement
上调用此方法,或者 SQL 语句没有返回ResultSet
对象
executeUpdate
int executeUpdate() throws SQLException
在此
PreparedStatement
对象中执行 SQL 语句,该语句必须是一个 SQL 数据操作语言(Data Manipulation Language,DML)语句,比如INSERT
、UPDATE
或DELETE
语句;或者是无返回内容的 SQL 语句,比如 DDL 语句。
返回:
(1) SQL 数据操作语言 (DML) 语句的行数
(2) 对于无返回内容的 SQL 语句,返回 0
抛出:
SQLException
- 如果发生数据库访问错误,在关闭的PreparedStatement
上调用此方法,或者 SQL 语句返回一个ResultSet
对象
使用PreparedStatement的优势
Statement 和 PrepareStatement 都可以实现数据库的增删改查等操作,但两者相比,PrepareStatement有如下优势
1.提高了代码的可读性和可维护性.
PrepareStatement 可以避免繁琐的SQL语句拼接操作。
例如 SQL语句中的
insert into student(stuNo,stuName,stuAge) values(5,'Meng',20)
如果其中字段值 用变量来表示
int stuNn = 5;
String stuName = "Meng";
int stuAge = 20;
但如果用 Statement方式执行时 需要将SQl语句拼接成
stmt.executeUpdate( " insert into student(stuNo,stuName,stuAge) values( "
+ stuNo + ", ' " + stuName + " '," + stuAge + " )" );
而如果 用PrepareStatement 方式执行时 就可以先用 ? 充当参数值的占位符
再用 setXXX() 方法设置 ? 的具体值, 以避免SQL语句的拼接操作
2.提高了SQL语句的性能
创建Statement对象时 不使用SQL语句做参数
例如 Statement stmt = connection.createStatement() ;
不会解析和编译SQL语句,而是每次调用executeUpdate()或者executeQuery()方法时 才会进行SQL语句的解析和编译操作
例如 stmt.executeUpdate("delete from student where stuNo = 5");
而创建 PrepareStatment 对象时 ,是使用带占位符 '?'的SQL语句作为参数
例如 PrepareStatement pstmt = connection.prepareStatement("delete from student where
stuName = ? and stuAge = ?");
会预先解析和编译该SQL语句,之后通过setXXX()方法给占位符'?'赋值 ,
最后执行SQL 语句时 无须再解析和编译SQL 语句 直接执行即可
例如 pstmt.executeUpdate();
这就使得,如果多次操作相同,就可以大大提高性能。 即 PrepaerStatement是预编译的SQL语句对象
3.提高了安全性,能有效地防止SQL注入攻击
使用PrepareStatement 的SQL语句对象 传入的任何数据 都不会和已经编译好的SQL语句进行拼接,从而避免了SQL注入攻击。
例如,在使用Statement时 。 可能会用以下代码来进行登录验证
stmt = connection.createStatement();
String querySQL = "select count(*) frrom login where
username='" + uname + "' and password = '"+ upwd + "'";
rs = stmt.executeQuery(querySQL);
...
if(rs.next()){
int result = rs.getInt("count(*)");
if(result>0){
//登录成功
}else{
//登录失败
}
}
上述代码看起来没有任何问题,
但试想如果用户输入的uname的值为是 “ 任意值' or 1=1 --"
upwd 密码输入任意值,
则SQL语句拼接后的结果如下
select count(*) from login where username ='XXX' or 1=1 -- 'and password = 'XXX'
在SQL语句中 用 "or 1=1" 使得where条件永远成立 并且用-- 将后面的SQL代码注视掉,
这样就造成了安全隐患(SQL注入) ,使得并不存在的用户名和密码也能登录成功。
而PrepaerStatement 中使用了占位符 '?' SQL语句预编译,
以及 setXxx()方法有效的避免的这种漏洞。