前言
🌟🌟本期讲解关于Spring IOC&DI的详细介绍~~~
🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客
🔥 你的点赞就是小编不断更新的最大动力
🎆那么废话不多说直接开整吧~~
目录
📚️1. #{} 与 ${}的使用
我们在之前的学习中,了解到了“#{}”,但是这里的${}是什么呢?其实这里的${}也具有参数传递的功能但是我们之前为什么不使用$符号呢?且听下面的分析过程~~~
1.1integer类型数据
我们可以通过id类整型参数的传递进行实验,首先得先创建一个数据库,如下所示:
接下来我们知己使用XML的方式进行代码的编写:
在Mapper类中:
List<UserInfo> select2(Integer id);
这里先定义数据的返回类型,然后再在XML文件中实现查询SQL的方法:
<select id="select2" resultType="com.example.mybatis.Model.UserInfo">
select * from user_info where id=#{id}
</select>
然后再测试类进行测试后们可以看到如下的打印的日志:
解释:
可以发现在SQL查询语句中,参数被“?”给替代了,然后下面的参数就是“2”,此时可以了解到我们输⼊的参数并没有在后⾯拼接,id的值是使⽤ ? 进⾏占位. 这种SQL 我们称之为"预编译SQL"
然后我们将这里的“#{ }” 替换成“${}”,具体的情况就是如下所示的:
解释:
可以发现此时SQL语句,就没有“?”,然后下面的paramters参数就为空了,然后我们就知道${} 会直接进⾏字符替换, ⼀起对SQL进⾏编译,不会像#号一样使用占位符;这种我们就称之为即时SQL
1.2String类型数据
这里我们使用String类来进行匹配查询,具体的操作还是和上面差不多;
Mapper类的代码如下:
List<UserInfo> selectAllByUsername(String username);
然后再XML写SQL语句的操作:
解释:
此时可以看到,和上面的string类型的数据是一样的,这里会标明参数的类型为string类型,然后再进行替换占位的时候会自动添加引号;
然后我们将这里的“#{ }” 替换成“${}”,具体的情况就是如下所示的:
<select id="selectAllByUsername" resultType="com.example.mybatis.Model.UserInfo">
select * from user_info where username=${username}
</select>
这里就是通过输入的名字进行查询,将这#号替换成了$符号,然后再测试类进行测试后打印的日志报错了,具体的打印日志如下所示:
解释:
这里可以看到此时的$符号的操作,出现了报错,原因就是BadSql,我们在上面看到,由于直接代替的原因,查询条件中字符串没有出现“ ' ' ”符号,即引号,然后就是SQL语句语法不正确导致错误;
解决办法:
在XML编写SQL语句的时候进行手动添加' ';
代码如下:
<select id="selectAllByUsername" resultType="com.example.mybatis.Model.UserInfo">
select * from user_info where username='${username}'
</select>
此时进行测试打印,打印的日志就是如下所示的:
解释:此时可以看到在字符串添加了“ ' ' ”双引号,然后参数仍然为空;
综上所述:
#{} 使⽤的是预编译SQL, 通过 ? 占位的⽅式, 提前对SQL进⾏编译, 然后把参数填充到SQL语句中. #{} 会根据参数类型, ⾃动拼接引号 '' .
${} 使用的就是即时编译SQL,会直接进⾏字符替换, ⼀起对SQL进⾏编译. 如果参数为字符串, 需要加上引号 ''
📚️2. #{} 与 ${}的区别
2.1性能
当客⼾发送⼀条SQL语句给服务器后, ⼤致流程如下:
1. 解析语法和语义, 校验SQL语句是否正确
2. 优化SQL语句, 制定执⾏计划
3. 执⾏并返回结果
⼀条 SQL如果⾛上述流程处理, 我们称之为 Immediate Statements(即时 SQL)
但是绝⼤多数情况下, 某⼀条 SQL 语句可能会被反复调⽤执⾏, 或者每次执⾏的时候只有个别的值不同(⽐如 select 的 where ⼦句值不同, update 的 set ⼦句值不同, insert 的 values 值不同). 如果每次都需要经过上⾯的语法解析, SQL优化、SQL编译等,则效率就明显不⾏了
总结:
所以预编译SQL就在执行上述的优化操作后,遇到同样的SQL语句,就不会对SQL进行再次的优化编译了,就直接改变参数,省去了解析优化等过程, 以此来提⾼效率
预编译SQL的性能比即时SQL的性能更高;
2.2安全性
这里出现的安全性就是(SQL注入)
SQL注⼊:是通过操作输⼊的数据来修改事先定义好的SQL语句,以达到执⾏代码对服务器进⾏攻击的⽅法。由于没有对⽤⼾输⼊进⾏充分检查,⽽SQL⼜是拼接⽽成,在⽤⼾输⼊参数时,在参数中添加⼀些SQL关键字,达到改变SQL运⾏结果的⽬的,也可以完成恶意攻击
注意:这里只针对的就是${ }符号;
假如我们在此符号中添加 ' or 1='1
然后在#{ }运行中,可以发现此时的此时的打印日志告诉我们,这里的字符串在数据库中没有找到
如下所示:
这里的结果确实如我们所料,但是在${ }符号中,如下所示:
解释:
哎奇怪,怎么会出现这种情况,这个字符串在我们的数据库列中就没有这个字段;但是为啥就全部搜索出来了呢??
因为拼接的问题和原因,所以这里出现了误判,' {' or 1='1} ' 拼接后成了以下SQL语句
' ' or 1='1'
解释:
具体的意思就是为空或者为true,这就是为啥全部搜索出来了,这里存在SQL关键字or;
所以SQL注⼊是⼀种⾮常常⻅的数据库攻击⼿段, SQL注⼊漏洞也是⽹络世界中最普遍的漏洞之⼀.
如果发⽣在⽤⼾登录的场景中, 密码输⼊为 ' or 1='1 , 就可能完成登录;
总之在后面的学习中能用#{} 那么就使用#{ },${ }非特殊情况尽量不要使用
📚️3.${ }使用场景
3.1排序
在实现排序功能的时候,由于“desc”不需要使用引号,所以这里我们就可以使用${}符号
具体的代码如下所示:
<select id="selectAllById" resultType="com.example.mybatis.Model.UserInfo">
select * from user_info order by id ${sort}
</select>
这里即时XML的写法,可以看到此时order by id然后排序关键词,就不需要引号,那么此时我们就可以使用$符号;
在测试类中的实现代码:
@Test
void selectAllById() {
userInfoXMLMapper.selectAllById("desc");
}
我们这里就是按照降序排序进行查询结果的排序的,最后打印的日志如下所示:
解释:
上面的两行就是SQL语句和参数,参数为空,然后即时SQL进行拼接,SQL语句就成为了一个查询语句按照降排序的方式进行查询结果的展示;
3.2模糊查询
代码如下所示:
<select id="selectByUsername" resultType="com.example.mybatis.Model.UserInfo">
select * from user_info where username like '%${username}%'
</select>
这里也是不需要引号,然后也可以使用$符号,在测试类中代码:
@Test
void selectByUsername() {
userInfoXMLMapper.selectByUsername("o");
}
最后打印的日志如下所示:
解释:
这里的模糊查询,中间的参数是不需要自动添加引号的,并且这里的模糊查询的条件就是查找名字里包含“o”的那一段数据;
但是这里由于注入等安全性,这里我们可以使用#进行另一种写法,具体的代码如下所示:
<select id="selectByUsername2" resultType="com.example.mybatis.Model.UserInfo">
select * from user_info where username like concat('%',#{username},'%')
</select>
解释:
这里使用concat关键字,实现需要引号的拼接操作,这样就可以使用#{}来进行参数的传递,几避免了SQL注入的安全问题,还可能提高了执行的效率;
📚️4.数据库连接池
4.1介绍
数据库连接池负责分配、管理和释放数据库连接,它允许应⽤程序重复使⽤⼀个现有的数据库连接,⽽不是再重新建⽴⼀个
没有使⽤数据库连接池的情况: 每次执⾏SQL语句, 要先创建⼀个新的连接对象, 然后执⾏SQL语句, SQL语句执⾏完, 再关闭连接对象释放资源. 这种重复的创建连接, 销毁连接⽐较消耗资源
使⽤数据库连接池的情况: 程序启动时, 会在数据库连接池中创建⼀定数量的Connection对象, 当客⼾请求数据库连接池, 会从数据库连接池中获取Connection对象, 然后执⾏SQL, SQL语句执⾏完, 再把Connection归还给连接池
优点:
1. 减少了⽹络开销
2. 资源重⽤
3. 提升了系统的性能
4.2使用
常⻅的数据库连接池:
• C3P0
• DBCP
• Druid
• Hikari
主流就是Hikari,Druid;
我们的SpringBoot默认使用的就是Hikari;日志如下所示:
可以看到这就是springboot默认使用的就是Hikari;
📚️5.总结
本期小编主要讲解了关于#{ },${ },的区别与如何进行使用,讲解了两者的性能比较,比较重要的SQL注入的问题,以及简单的阐述了数据库连接池的介绍~~~
🌅🌅🌅~~~~最后希望与诸君共勉,共同进步!!!
💪💪💪以上就是本期内容了, 感兴趣的话,就关注小编吧。
😊😊 期待你的关注~~~