Java MyBatis(二)--- 多表查询,# 和 $的区别,SQL注入,数据库连接池,动态SQL
文章目录
- MyBatis
- 其它查询操作
- 多表查询
- # 和 $ 的区别
- SQL注入
- 数据库连接池
- 数据库的规范
- 动态SQL
- 增
- 查询
- < set > 标签(更新)
- 删除
- < sql > < include > 标签
MyBatis
- 注解的方式和xml的方式可以在同一个类中共存(可以在同一个类中使用)
其它查询操作
多表查询
- 工作中尽量避免使用多表查询,尤其是对性能要求非常高的项目(多表查询比较慢)
- 多表查询
多表查询,其实和单表查询是一样的,都是把结果映射到一个对象中,只不过多表查询映射的对象的属性要增加一些(在你写的类中增加你没有的属性,但是是你要查询的属性)
# 和 $ 的区别
1. 最常见的面试题就是 # 和 $ 的区别
2. # 和 $ 都是为了获取变量的值
(1) 使用 # 查询
(2) 使用 $ 查询
区别:
使用 # 时,如果参数为String,会自动加上 ‘’,$ 不会,$ 符号是直接拼接,$ 如果是字符串类型,需要加上 ‘’(需要自己拼接上引号)
如果不管怎样,使用 $ 都加上引号(‘’),虽然mysql会帮我们转换类型,但是会有性能上的影响
mysql 帮我们把String类型转换为了Integer类型
3. 有些场景必须使用 $ 符号,而不能使用 #
(1)比如:排序时,不能使用 #,如果使用 # 会给参数加上 ‘’
(2) 模糊查询的时候,不能使用#
SQL注入
很重要,面试主要就是答这一点:
4. $ 存在的漏洞,SQL注入
SQL注入:
这样的语句就是,不管怎样都是查询全部的内容了
4. 预编译SQL和即时SQL的区别:
SQL 执行分为三步:
(1) 语法解析
(2) SQL 优化
(3) SQL 执行
预编译SQL:相当于模版,语法解析和SQL优化都不需要做了,只需要改变参数进行执行,速度上更快
即时SQL:每次都需要全部进行下面的全部的步骤
5. 为什么 # 不存在sql注入,$ 存在 sql注入??
#是会预留一个参数的位置,只能把参数放到那个位置上,也只能占一个格子的位置
$是直接进行拼接,可能会占用多个格子的位置,就出现了参数解析的问题(’ ’ or 1 = '1 ')
比如你火车上的位置都是一格一格的,你只能在你的坐在你的那格(就是#),如果你可以占用其它格(就是$)
排序的时候,不能使用 $,会出现sql注入的问题,可以在传参的时候,进行判断是否是asc或者是desc,如果是这两个就可以使用 $ ,不是就不使用 $,这样就避免了sql注入
模糊查询的时候,也会出现$ 的sql注入,所以提供了一个函数解决问题(并且这个函数可以使用#)
CONCAT函数,配置#的使用,进行模糊查询:
- 总结:
数据库连接池
- 池化技术,数据库连接池的出现,就没有创建连接和销毁连接的消耗了,直接从池子里拿和放
Hikari(日语光的意思,追求的是性能):就是一个数据库连接池,是SpringBoot默认使用的
- 如果我们想把默认的数据库连接池切换为Druid(阿里的数据库连接池,功能强大,有很多功能)数据库连接池, 只需要引入相关依赖即可
引入到xml文件中:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>1.2.21</version>
</dependency>
日志打印的数据库连接池的开启和关闭:
- 常见的数据库连接池:
数据库的规范
-
表名, 字段名使用写字母或数字, 单词之间以下划线分割. 尽量避免出现数字开头或者两个下划线中间只出现数字. 数据库字段名的修改代价很大, 所以字段名称需要慎重考虑。
-
表必备三字段: id, create_time,update_time(有同等含义的字段即可, 字段名不做强制要求)
-
在表查询中, 避免使用 * 作为查询的字段列表, 标明需要哪些字段
-
#{} 和 ${} 的区别:
动态SQL
- 动态SQL:根据用户的需求,动态的拼接sql
- 增删改查
增
- 数据插入时,需求:根据用户的输入情况,进行插入
性别是否为空:
- 注解:
(1) 把全部的sql放在script标签下
(2) 使用if标签
gender对应的是java的属性,因为java属性才有值,字段是没有值的
@Mapper
public interface UserInfoMapper2 {// 实现@Insert("<script>" +"insert into user_info (username,password,age," +"<if test = 'gender!=null'>gender,</if>" +"phone)" +"values(#{username},#{password},#{age}," +"<if test = 'gender!=null'>#{gender},</if>" +"#{phone})" +"</script>")// 声明Integer insert2(UserInfo userInfo);// 实现}
- xml的写法:
(1) xml更加易读
(2) 书写时有提示
// 声明
Integer insertByXML(UserInfo userInfo);// 实现
<insert id="insertByXML">insert into user_info (username,password,age,<if test="gender != null">gender,</if>phone)values(#{username},#{password},#{age},<if test="gender != null">#{gender},</if>#{phone})</insert>
非动态sql,不写的时候是null
4. 逗号不管放在哪里,总会多一个,导致sql的格式错误,这该如何解决呢??
解决办法:
< trim > 帮助我们去除多余的字符
< trim > 代码块的作用:
prefix(在最前面添加字符)和suffix(在最后面添加字符)
查询
- 使用trim标签和where标签结果是等价的,都可以实现去除多余标签的功能
// 使用where去除and<select id="selectByCondicition" resultType="com.rzj.demo.demos.model.UserInfo">select * from user_info<where><if test="username != null">username = #{username}</if><if test="age != null">and age = #{age}</if><if test="gender != null">and gender = #{gender}</if></where></select>// 使用trim去除and<select id="selectByCondicition" resultType="com.rzj.demo.demos.model.UserInfo">select * from user_infowhere<trim prefixOverrides = "and"><if test="username != null">username = #{username}</if><if test="age != null">and age = #{age}</if><if test="gender != null">and gender = #{gender}</if></where></select>
trim标签存在的问题:如果所有条件都为空时,SQL 语句会变成:select * from user_info where
如果查询条件都为空时,where标签会自动去除where关键字,还会帮我们去除最前面的and字符
三个参数都为空的时候(usename,age,gender):
注解的方式实现:
< set > 标签(更新)
-
update user_info set a = ?,b = ? where c = ?
-
使用set标签去除后面的逗号
-
使用set标签去除后面的逗号
删除
- 使用 < foreach > 标签进行删除
- < foreach > 的使用(foreach就是表示循环):
当方法参数是单个集合且没有使用 @Param 注解时,MyBatis 默认的参数名是:
collection和list
// 批量deleteInteger batchDelete(List<Integer> ids);@Testvoid batchDelete() {userInfoMapper2.batchDelete(Arrays.asList(12,13,14,15));}<delete id="batchDelete">delete from user_infowhere id in<foreach collection="collection" separator="," item="id" open="(" close=")">#{id}</foreach></delete>
没有重命名,默认集合参数使用 collection 或者是 list
< sql > < include > 标签
- 把一些重复的sql可以提取出来,使用< sql >标签标识。
使用时,使用< include > 标签