PreparedStatement vs Statment
一、语法不同:PreparedStatement可以使用预编译的sql,而Statement只能使用静态的sql。
二、效率不同: PreparedStatement可以使用sql缓存区,效率比Statement高。
三、安全性不同: PreparedStatement可以有效防止sql注入,而Statement不能防止sql注入。
通过案例对比来给大家讲解这一点:
1、Statement模拟用户登陆:
package sram.login;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
import sram.util.jdbc.JdbcUtil;
/**
* 模拟用户登录效果
*/
public class Demo1 {
//模拟用户输入
private String name = "zhangsan";
private String password = "123";
@Test
public void testByStatement(){
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//获取连接
conn = JdbcUtil.getConnection();
//创建Statment
stmt = conn.createStatement();
//准备sql
//注意带参的sql语句的书写
String sql = "SELECT * FROM admin WHERE userName='"+name+"' AND pwd='"+password+"'";
System.out.println(sql);
//执行sql
rs = stmt.executeQuery(sql);
if(rs.next()){
//登录成功
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
JdbcUtil.close(conn, stmt,rs);
}
}
}
乍一看没什么问题啊,可以识别用户,判断是否登陆成功,但是接下来给大家介绍这样的一个情况:
1)首先引入这样一个概念:sql语句被注入
2)接下来我们稍稍修改下刚才的代码:
3)而PreparedStatement接口则不存在这种问题。
2、PreparedStatement模拟用户登陆:
package sram.login;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
import sram.util.jdbc.JdbcUtil;
/**
* 模拟用户登录效果
*/
public class Demo1{
//模拟用户输入:SELECT * FROM admin WHERE userName='zhangsan' OR 1=1 -- 'AND pwd='123';
private String name = "用户随意输入' OR 1=1 -- ";
private String password = "密码任意";
/**
* Statment存在sql被注入的风险
*/
//public void testByStatement(){}
/**
* PreparedStatement可以有效地防止sql被注入
*/
@Test
public void testByPreparedStatement(){
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
//获取连接
conn = JdbcUtil.getConnection();
String sql = "SELECT * FROM admin WHERE userName=? AND pwd=?";
//预编译
stmt = conn.prepareStatement(sql);
//设置参数
stmt.setString(1, name);
stmt.setString(2, password);
//执行sql
rs = stmt.executeQuery();
if(rs.next()){
//登录成功
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
System.out.println(sql);
System.out.println(stmt);
System.out.println(rs);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
JdbcUtil.close(conn, stmt ,rs);
}
}
}
运行结果:
推荐使用PreparedStatement