PreparedSatement预编译对象
目标
能够理解什么是SQL注入
能够理解PreparedSatement的执行原理
讲解
SQL注入问题
在我们前一天JDBC实现登录案例中,当我们输入以下密码,我们发现我们账号和密码都不对竟然登录成功了
请输入用户名:
hehe
请输入密码:
a' or '1'='1
问题分析:
// 代码中的SQL语句
"SELECT * FROM user WHERE name='" + name + "' AND password='" + password + "';";
// 将用户输入的账号密码拼接后
"SELECT * FROM user WHERE name='hehe' AND password='a' or '1'='1';"
我们让用户输入的密码和SQL语句进行字符串拼接。用户输入的内容作为了SQL语句语法的一部分,改变了原有SQL真正的意义,以上问题称为SQL注入。
要解决SQL注入就不能让用户输入的密码和我们的SQL语句进行简单的字符串拼接。需要使用PreparedSatement类解决SQL注入。
PreparedSatement的执行原理
继承结构:
我们写的SQL语句让数据库执行,数据库不是直接执行SQL语句字符串。和Java一样,数据库需要执行编译后的SQL语句(类似Java编译后的字节码文件)。
Satement
对象每执行一条SQL语句都会先将这条SQL语句发送给数据库编译,数据库再执行。
Statement stmt = conn.createStatement();
stmt.executeUpdate("INSERT INTO users VALUES (1, '张三', '123456');");
stmt.executeUpdate("INSERT INTO users VALUES (2, '李四', '666666');");
上面2条SQL语句我们可以看到大部分内容是相同的,只是数据略有不一样。数据库每次执行都编译一次。如果有1万条类似的SQL语句,数据库需要编译1万次,执行1万次,显然效率就低了。
prepareStatement()
会先将SQL语句发送给数据库预编译。PreparedStatement
会引用着预编译后的结果。可以多次传入不同的参数给PreparedStatement
对象并执行。相当于调用方法多次传入不同的参数。
String sql = "INSERT INTO users VALUES (?, ?, ?);";
// 会先将SQL语句发送给数据库预编译。PreparedStatement会引用着预编译后的结果。
PreparedStatement pstmt = conn.prepareStatement(sql);
// 设置参数
pstmt.setString(1, 1);
pstmt.setInt(2, "张三");
pstmt.setString(3, "123456");
pstmt.executeUpdate();
// 再次设置参数
pstmt.setString(1, 2);
pstmt.setInt(2, "李四");
pstmt.setString(3, "66666");
pstmt.executeUpdate();
上面预编译好一条SQL,2次传入了不同的参数并执行。如果有1万条类似的插入数据的语句。数据库只需要预编译一次,传入1万次不同的参数并执行。减少了SQL语句的编译次数,提高了执行效率。
示意图
PreparedSatement的好处
prepareStatement()
会先将SQL语句发送给数据库预编译。PreparedStatement
会引用着预编译后的结果。可以多次传入不同的参数给PreparedStatement
对象并执行。减少SQL编译次数,提高效率。- 安全性更高,没有SQL注入的隐患。
- 提高了程序的可读性## PreparedSatement的API介绍
目标
能够掌握PreparedSatement相应的API
讲解
获取PreparedSatement
在java.sql.Connection
有获取PreparedSatement
对象的方法
PreparedStatement prepareStatement(String sql)
会先将SQL语句发送给数据库预编译。PreparedStatement对象会引用着预编译后的结果。
PreparedSatement的API介绍
在java.sql.PreparedStatement
中有设置SQL语句参数,和执行参数化的SQL语句的方法
-
void setDouble(int parameterIndex, double x) 将指定参数设置为给定 Java double 值。
-
void setFloat(int parameterIndex, float x) 将指定参数设置为给定 Java REAL 值。
-
void setInt(int parameterIndex, int x) 将指定参数设置为给定 Java int 值。
-
void setLong(int