接口 PreparedStatement execute() executeQuery() executeUpdate() 以及SQL注入

6 篇文章 0 订阅

execute

boolean execute()
                throws SQLException

在此 PreparedStatement 对象中执行 SQL 语句,该语句可以是任何种类的 SQL 语句。一些预处理过的语句返回多个结果,execute 方法处理这些复杂的语句,executeQueryexecuteUpdate 处理形式更简单的语句。

execute 方法返回一个 boolean 值,指示第一个结果的形式。必须调用 getResultSetgetUpdateCount 方法获取该结果,必须调用 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)语句,比如 INSERTUPDATEDELETE 语句;或者是无返回内容的 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()方法有效的避免的这种漏洞。

     

  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
一个PreparedStatement对象可以执行不同的SQL语句,只需要在创建PreparedStatement对象时,传入不同的SQL语句即可。具体步骤如下: 1. 创建Connection对象,连接到数据库。 2. 使用Connection对象的prepareStatement方法创建一个PreparedStatement对象,该对象表示预编译的SQL语句。 3. 设置PreparedStatement对象中占位符对应的参数值。 4. 执行SQL语句,使用PreparedStatement对象的executeexecuteQueryexecuteUpdate方法,根据SQL语句的类型选择相应的方法。 5. 重复步骤2-4,使用不同的SQL语句,执行不同的操作。 以下是一个示例代码: ``` // 创建Connection对象 Connection conn = DriverManager.getConnection(url, username, password); // 创建PreparedStatement对象,并执行第一个SQL语句 PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE name = ?"); pstmt.setString(1, "Tom"); ResultSet rs = pstmt.executeQuery(); // 执行第二个SQL语句 pstmt = conn.prepareStatement("INSERT INTO users(name, age) VALUES(?, ?)"); pstmt.setString(1, "Jerry"); pstmt.setInt(2, 20); int rows = pstmt.executeUpdate(); // 关闭资源 rs.close(); pstmt.close(); conn.close(); ``` 在上面的代码中,首先创建了一个Connection对象,然后使用该Connection对象的prepareStatement方法创建了一个PreparedStatement对象,并执行了第一个SQL语句。接下来,使用同一个PreparedStatement对象,执行了第二个SQL语句。最后,关闭了ResultSet、PreparedStatement和Connection对象。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值