1.作用:防止sql注入,且性能更好。
2.什么叫sql注入:所谓sql注入是指通过操作输入修改事先定义好的sql语句,达到执行代码攻击服务器的方法。
2.1.为了帮助理解这里举个以前在b站听的视频课中的例子:
2.1.1. 数据库中存在一个user表,内容有:id=1,username=‘张三’,password=‘123’;
2.1.2. 创建一个模拟用户登录的login类,先写好主方法进行jdbc‘连接数据库七步曲’;
2.1.3. 连接好数据库后,设置用户账号string name=‘张三’,stringpwd=‘123’;
2.1.4.写个sql语句:sql=“select * from user where username=‘ “+ name + ” ’ and password=‘ “+pwd ” ’ ”;
2.1.5.写个判断语句:if(rs.next()){
systme.out.println("登陆成功");
}else{
systme.out.println("登陆失败");
这个模拟结果肯定是登录成功的。
2.1.6.但是当我们把用户名和密码随便写呢:
此时我们会发现登录结果依然登陆成功
2.1.7那么为什么会造成这种情况呢?我们将此时的sql语句进行打印看看输出的sql语句是我们想象中的那样吗?
2.1.8我们发现此时sql语句的含义变了or变成了sql语句中的判断含义的关键字了,and这里的条件虽然比or先执行,但是and那里的执行结果为false,而or后面的结果是true,从而导致where整个条件结果都为true,此时谁都可以随便登录成功进行任何操作了。所以这就是一个简单的sql注入演示。
3.那么我们如何防止sql注入呢?此时PreparedStatement就来了:
3.1.获取PreparedStatement:
PreparedStatement pstmt = conn.prepareStatement(sql);
3.2.sql语句也要改成参数用占位符?代替,主要就是为了解决上面在sql语句中拼接字符串的操作:
sql="select * from tb_user where username = ? and password = ?";
3.3.有了占位符?,我们要给这个?设值,就会用到PreparedStatement提供的方法:
setXxx(参数1,参数2):给 ? 赋 值
Xxx:数据类型 ; 如 setInt (参数1,参数2)
参数:
参数1: ?的位置编号,从1 开始
参数2: ?的值;
3.4.执行SQL语句:
executeUpdate();执行DDL语句和DML语句
executeQuery(); 执行DQL语句
==注意:== 调用这两个方法时不需要传递SQL语句,因为获取SQL语 句执行对象时已经对SQL语句进行预编译了
4.PreparedStatement原理:预编译SQL,性能更高; 防止SQL注入将敏感字符进行转义
4.1将sql语句发送到MySQL服务器端 MySQL服务端会对sql语句进行如下操作
4.1.1 检查SQL语句 检查SQL语句的语法是否正确。
4.1.2编译SQL语句。将SQL语句编译成可执行的函数。
4.1.3检查SQL和编译SQL花费的时间比执行SQL的时间还要长。如 果我们只是重新设置参数,那么检查SQL语句和编译SQL语 句将不需要重复执行。这样就提高了性能。 执行SQL语句.
4.1.4在获取PreparedStatement对象时,将sql语句发送给mysql 服务器进行检查,编译(这些步骤很耗时) 执行时就不用再进行这些步骤了,速度更快 如果sql模板一样,则只需要进行一次检查、编译