Java JDBC
数据库连接的时候创建一个对象,然后通过对象去调用executeQuery方法来执行sql语句

Statement

  1. String sql = "select * from users";
  2. Statement stmt = db.conn.createStatement();
  3. ResultSet rs = stmt.executeQuery(sql);

PrepareStatement

  1. String sql = "select * from users where username=? and userpwd=?";
  2. PreparedStatement preStmt = db.conn.prepareStatement(sql);
  3. pstmt.setString(1, username);
  4. pstmt.setString(2, userpwd);
  5. preStmt.executeUpdate();
  6. preStmt.close();

PrepareStatement继承自Statement

可读性

PrepareStatement可以将SQL语句中的变量抽象出来,这样可以提高代码的可读性 ;

效率

Statement 执行每一条SQL语句时,都是编译+执行,相当于静态SQL;
PrepareStatement执行的SQL语句,会进行预编译,SQL中可以包含动态参数”?”,在执行时可以为”?”动态设置参数值,当下次执行相同类型的SQL语句时,可以解析并直接执行编译好的SQL语句,从而减少编译次数提高数据库的性能,相当于动态SQL;另一方面,他还有Batch功能可以进行批量请求,从而减少了JDBC驱动和数据库的连接请求次数,eg:

  1. PreparedStatement pstmt = conn.prepareStatement("INSERT into users values (?, ?, ?)");
  2. for (i = 0; i < list.length(); i++) {
  3. pstmt.setLong(list[i].id);
  4. pstmt.setString(list[i].name);
  5. pstmt.setString(list[i].phone);
  6. pstmt.addBatch();
  7. }
  8. pstmt.executeBatch();

~Statement每次执行sql语句,数据库都要执行sql语句的编译 ,最好用于仅执行一次查询并返回结果的情形时,效率高于PreparedStatement

安全性

Statement:SQL语句每次都是重新编译执行的,这就导致你传进去的参数和SQL语句是有联系,可以改变原先SQL的功能结构

  1. select * from user where username= '"+name+"' and userpwd='"+passwd+"'

如果传进去的passwd参数值是or '1' = '1'那SQL就变成了永真式:

  1. select * from user where username= '"+name+"' and userpwd='' or '1' = '1'

权限就这样被轻易获取了;
PrepareStatement:SQL的参数会被强制类型转换成表中的列属性值,由于SQL语句已经实现被编译过,参数和原来SQL语句不会有交集,也就避免了这种情况的发生。