为什么推荐使用PreparedStatement而不是Statement?

在JDBC应用中,有经验的开发者,大多都使用PreparedStatement代替Statement

那么,这是为什么呢?

原因基于以下几点:

1.代码的可读性和可维护性

首先,让我们来看看使用Statement的查询SQL语句,只能采用拼接的方法传入参数

int id = 1;

String name = "rachel";

String sql = "select * from memo_group where id='"+id+"'or name='"+name+"'";
            
Statement statement = connection.createStatement();
           
ResultSet resultSet = statement.executeQuery(sql); 

而PreparedStatement可以传入带占位符的SQL语句,提供了补充占位符变量的方法

String sql = "select * from memo_group where id = ? or name= ? ";
            
prepareStatement preStatement = connection.prepareStatement(sql);

preStatement.setInt(1,groupId);
    
preStatement.setString(2,groupName);
           
ResultSet resultSet = statement.executeQuery();
           

 由上述例子可知,PreparedStatement可以实现SQL语句的参数化

PreparedStatement接口继承Statement,作为 Statement 的子类,PreparedStatement 继承了Statement 的所有功能。另外它还添加了一整套方法,用于设置发送给数据库以取代 IN 参数占位符的值。 

包含于 PreparedStatement 对象中的 SQL 语句可具有一个或多个 IN 参数。IN参数的值在 SQL 语句创建时未被指定。该语句为每个 IN 参数保留一个问号(“?”)作为占位符。每个问号的值必须在该语句执行之前,通过适当的setXXX 方法来提供。

in(?)输入一个参数

 String sql = "select id,name,created_time,modify_time from memo_group where name in(?) ";
 statement = connection.prepareStatement(sql);
 //参数赋值 parameterIndex 1开始
 statement.setString(1,names);
 resultSet = statement.executeQuery();
         
public static void main(String[] args) {
  //where name in (?)
  //where name in ('C++','default');
  //? 不能多作为多参数,多个参数就写多个?
     queryMemoGroup("'C++','default'");
      
    }

 注意:?不能作为多参数,需要传入多个参数时,就需要写多个?

扫描二维码关注公众号,回复: 9748534 查看本文章

in(?)输入多个参数

StringBuilder sb = new StringBuilder();
sb.append("select id,name,created_time,modify_time from memo_group where name in(");
    for (int i = 0; i < names.length; i++) {
             sb.append("?,");
        }
    sb.setLength(sb.length()-1);
    sb.append(")");

statement = connection.prepareStatement(sb.toString());
 //参数赋值 parameterIndex 1开始
 for (int i=0;i<names.length;i++){
      statement.setString(i+1, names[i]);
     }
                 
public static void main(String[] args) {
   //where name in (?)
   //where name in ('C++','default');
   queryMemoGroup("C++","default","Java");
        
    }

2.PreparedStatement尽最大可能提高性能  

(1)Statement

Statement statement = conn.createStatement();  //创建
ResultSet rSet = statement.executeQuery(sql);  //执行

(2)PreparedStatement

PreparedStatement preStatement = conn.prepareStatement(sql);  //创建
ResultSet pSet = preStatement.executeQuery();                 //执行

由上可以看出,PreparedStatement有预编译的过程,已经绑定SQL,之后无论执行多少遍(修改SQL语句中的参数),都不会再去进行编译,而 statement 不同,执行多少次,就要编译多少次SQL,因此,当执行数据量特别大时,PreparedStatement的数据库访问效率要远远高于 Statement。

3.防止SQL注入

首先,什么是SQL注入呢?让我们先来看一个例子:

String sql = "select * from memo_group where id='"+id+"' or '1=1'";

因为"1=1"肯定成立,所以该SQL语句判断条件也一定成立

在使用参数化查询的情况下,数据库系统不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行。而Statement采用字符拼接的方式,一旦有人恶意使用破坏性指令,就会造成数据库泄漏。

使用PreparedStatement的参数化的查询可以阻止大部分的SQL注入

发布了50 篇原创文章 · 获赞 39 · 访问量 8269

猜你喜欢

转载自blog.csdn.net/Racheil/article/details/95240313