Day09-03.Mybatis-基础操作-删除(预编译SQL)
1.MyBatis这个框架底层执行了什么样的SQL语句,执行的结果是什么样的,并没有直观的看到。而在MyBatis框架中,我们可以借助MyBatis的日志来看到这些信息的,这些日志默认的关闭的,要想看到这些日志信息,就需要再application.properties当中打开MyBatis的日志。
2.日志输出:
可以在application.properties当中,打开MyBatis的日志,并指定输出到控制台。
#指定mybatis输出日志的位置,输出控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
==> Preparing: delete from emp where id = ?
==> Parameters: 16(Integer)
<== Updates: 0
第一行的?是一个参数占位符,最终这条SQL语句在运行的时候会使用下面的参数(也就是16),来替换掉什么的这个参数占位符?然后删除id等于16的这个员工信息。Updates=0,代表的是当前这条delete语句它影响的记录数为0。
上面两条语句叫做预编译SQL。如果我们在mybatis的Mapper接口中声明的SQL语句是使用#{}这种占位符,那最终#{}会被?替代,生成这样一个预编译SQL。这个?实际上就是预编译SQL当中的参数占位符。
3.SQL语句的执行过程:
我们在Java程序中编写了一条SQL语句,SQL语句要想执行就需要连接上数据库,然后将SQL语句发送给MySQL数据库服务器,而这条SQL语句发送给MySQL数据库服务器之后,数据库并不是立即就执行,而是要经历一系列的过程。比如要对SQL语句的语法进行 (SQL语法解析检查) =》(优化SQL) =》(编译SQL) =》(执行SQL) 这几步操作。而为了提高效率,在数据库当中它会将优化编译后的SQL缓存起来,这个缓存实际就是一块内存区域,就是来存储数据的。缓存起来之后,下一次再执行SQL语句的时候,它会先检查缓存,看一下缓存当中是否有编译好的SQL语句,如果有就不用再执行这一系列的操作了,直接去执行SQL语句。如果没有,就又需要执行这一系列的操作,再把编译后的结果缓存起来。
4.预编译SQL的优势
1.性能更高
解释:
1.正常的非预编译形式的SQL语句:(如果要执行三条SQL语句,分别删除id为1,2,3的员工信息)(如果删除100个员工,就要编译100次)
delete from emp where id = 1;
delete from emp where id = 2;
delete from emp where id = 3;
缓存当中缓存的是这三条SQL语句,id = 2用不了其他缓存好的SQL,需要重新缓存。(仅仅因为ID的值不一样)
2.采用预编译SQL语句:(如果要执行三条SQL语句,分别删除id为1,2,3的员工信息)(即使删除100个员工,也只需要编译一次)
delete from emp where id = ?;
并不会把字段值直接拼接在SQL语句当中,而是用于?这个占位符
首先删除ID为1的这条数据,它会将这个SQL语句发送给数据库,同时也会将1这个参数值也发送给数据库,数据库首先也会检查缓存当中是否有数据,如果缓存当中没有,接下来进行SQL语句的解析检查,优化,编译。操作完了会将编译后的结果加入到缓存当中,接下来才来执行这条SQL语句。而在执行这条SQL语句的时候,它会使用这个参数值将这个?直接替换掉。删除ID为2的数据,执行的SQL是一样的,此时缓存中已经缓存了这条SQL了,就不用再去执行这一系列的过程了。从缓存当中拿到编译之后的SQL语句,直接就去执行了。删除ID为3的数据也是一样的。
2.更安全(放置SQL注入)
1.SQL注入:
SQL注入是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的行为。
select count(*) from emp where username = 'zhangwuji' and password = '' or '1' = '1';
这样密码错了但是能登录
而如果使用预编译SQL,他会使用?作为参数占位符,会把(’ or ‘1’ = '1)当做一个字符串,拒绝花里胡哨。
5.如果我们使用的是Mybatis这样的框架,我们怎么样来选择我们要使用预编译的SQL语句呢?
其实只需要在定义SQL语句的时候,使用#{}这个占位符,最终生成的就是预编译的SQL语句,这个#{}最终就会被?给替换掉。
6.参数占位符:
1.#{…}
1.执行SQL时,会将#{…}替换为?,生成预编译SQL,会自动设置参数值。
2.使用时机:参数传递,都使用#{…}
2.${…}(使用场景很少)
1.拼接SQL。直接将参数拼接在SQL语句中,存在SQL注入问题。
2.使用时机:如果对表名、列表进行动态设置时使用。
7.小结:
1.根据ID删除员工:
1.@Delete("delete from emp where id = #{id}") delete from emp where id = ?
public void delete(Integer id);
2.@Delete("delete from emp where id = ${id}") delete from emp where id = 1
public void delete(Integer id);