论述题 12.  Statement与PreparedStatement的区别是什么?
【正确答案】Statement用于执行不带参数的简单SQL语句,每次执行SQL语句时,数据库都要编译该SQL语句。以下是一个最简单的SQL语句:
   Statement stmt=conn.getStatement();
   stmt.executeUpdate("insert into client values('aa','aaaa')");
   而PreparedStatement表示的是预编译的SQL语句的对象,用于执行带参数的预编译SQL语句。CallableStatement提供了用来调用数据库中存储过程的接口,如果有输出参数要注册,则说明是输出参数。下面给出一个使用PreparedStatement的例子。
   import java.sql.*;
   public class Test{
   public static void main(String[]args)throws Exception{
   String user="user1";
   String password="pwd1";
   String url="jdbc:mysq1://localhost:3306/Test";
   String driver="com.mysq1.jdbc.Driver";
   Connection con=null;
   PreparedStatement strut=null;
   ResultSet rs=null;
   try{
   Class.forName(driver);
   con=DriverManager getConnection(url,user,password);
   stmt=con.prepareStatement("select*from Employee where id=?");
   stmt.setInt(1,1);
   rs=stmt.executeQuery();
   while(rs.next()){
   System.out.println(rs.getInt(1)+" "+rs.getString(2)+" "+rs.getInt(3));
   }
   }
   catch(SQLException e1){
   e1.printStackTrace();
   }finally{
   try{
   if(rs!=null)
   rs.close();
   if(stmt!=null)
   stmt.close();
   if(con!=null)
   con.close();
   }
   catch(SQLException e){
   System.out.println(e.getMessage());
   }
   }
   }
   }
   程序的运行结果为:
   1 Jamesl 25
   虽然Statement对象与PreparedStatement对象能够实现相同的功能,但相比之下,PreparedStatement具有以下优点:
   (1)效率更高
   在使用PreparedStatement对象执行SQL命令时,命令会被数据库编译与解析,并放到命令缓冲区。然后,每当执行同一个PreparedStatement对象时,由于在缓冲区中可以发现预编译的命令,虽然它会被再解析一次,但不会被再次编译,是可以重复使用的,能够有效提升系统性能。所以,如果要执行插入、更新、删除等操作,最好使用PreparedStatement。鉴于此,PreparedStatement适用于存在大量用户的企业级应用软件中。
   (2)代码可读性和可维护性更好
   例如,以下两种方法分别使用Statement与PreparedStatement来执行SQL语句:
   方法1:
   stmt.executeUpdate("insert into t(coll,col2)values("+varl+","'+var2+"")");//stmt为Statement的一个对象
   方法2:
   //con是Connectiond得到一个对象
   PreparedStatement perstmt=con.prepareStatement("insert into tb_name(coll,col2)values(?,?)");
   perstmt.setString(1,var1);
   perstmt.setString(2,var2);
   显然,方法2具有更好的可读性。
   (3)安全性更好
   使用PreparedStatement能够预防SQL注入攻击。所谓SQL注入,指的是把用户输入的数据拼接到SQL语句后面作为SQL语句的一部分执行,例如,在代码中使用下面的SQL语句:sql="select top 1*fromuser where name=‘”+name+“’and password=‘”+password+“”’来验证用户名和密码是否正确,其中,name和password是用户输入的内容,当用户输入用户名aa,密码bb’or’a’=’a,那么拼接出来的SQt。语句就为select top 1*from user where name=‘aa’and password=‘bb’or‘a’=‘a’,只要user表中有数据,这条SQL语句就会有返回结果。这就达到了SQL注入的目的,而使用PreparedStatement就可以避免这种情况的发生。
【答案解析】