⭐️前言⭐️
这篇文章,我们就来完成MyBatis的增删改查操作,体会高级框架带来的灵活与简便。
用于进行操作的数据库数据表:
-- 创建数据库
drop database if exists mycnblog;
create database mycnblog DEFAULT CHARACTER SET utf8mb4;
-- 使用数据数据
use mycnblog;
-- 创建表[用户表]
drop table if exists userinfo;
create table userinfo(
id int primary key auto_increment,
username varchar(100) not null,
password varchar(32) not null,
photo varchar(500) default 'default.png',
createtime datetime default now(),
updatetime datetime default now(),
`state` int default 1
) default charset 'utf8mb4';
-- 创建文章表
drop table if exists articleinfo;
create table articleinfo(
id int primary key auto_increment,
title varchar(100) not null,
content text not null,
createtime datetime default now(),
updatetime datetime default now(),
uid int not null,
rcount int not null default 1,
`state` int default 1
)default charset 'utf8mb4';
-- 创建视频表
drop table if exists videoinfo;
create table videoinfo(
vid int primary key,
`title` varchar(250),
`url` varchar(1000),
createtime datetime default now(),
updatetime datetime default now(),
uid int
)default charset 'utf8mb4';
-- 添加一个用户信息
INSERT INTO `mycnblog`.`userinfo` (`id`, `username`, `password`, `photo`, `createtime`, `updatetime`, `state`) VALUES
(1, 'admin', 'admin', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1);
-- 文章添加测试数据
insert into articleinfo(title,content,uid)
values('Java','Java正文',1);
-- 添加视频
insert into videoinfo(vid,title,url,uid) values(1,'java title','http://www.baidu.com',1);
欢迎点赞 收藏 ⭐留言评论 私信必回哟
博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言
博客中涉及源码及博主日常练习代码均已上传GitHub
具体实现如下:
1、 在mapper
包下(interface)添加方法声明.
3.单元测试
注解@Transactional
表示该事务在测试完成后会自动回滚,这也是单元测试的优点,不会污染数据库。
测试结果:
1、在mapper(interface)
里面添加删除的代码声明
注解@Param
中的参数需要与xml
中的参数对应。
1、在mapper(interface)
里面添加修改的代码声明
2、在xml
中添加< update >标签和具体要执行的SQL
3.单元测试
测试结果:
预编译处理是指:MyBatis在处理#{}时,会将SQL中的#{}替换为?号,使用PreparedStatement的set方法来赋值。
直接替换是指:MyBatis在处理$ {}时,就直接把${}替换成变量的值。
下边通过几个例子来具体了解一下两者的差别:
针对int类型的参数进行查询
使用#{},可以在测试结果中发现,就是把#{}替换成了?占位符,进行预编译处理。
使用${},可以在测试结果中发现,就直接把 ${}替换成变量的值。
但是针对int类型的参数两种占位符都完成了查询,下边我们来看
针对String类型的参数进行查询
使用#{}参数占位符
使用${}参数占位符
发现在使用${}占位符去进行查询时,会发生报错,这是因为通过#{}占位符去进行查询的时候,默认加上了单引号,拼装的SQL就成了select * from userinfo where username='张三'
,而通过 ${}占位符去进行查询的时候直接替换但并没有加上单引号,拼装的SQL就成了select * from userinfo where username=张三
,所以会SQL报错。
总结
#{}和${}的区别
1.定义不同:#{}是预处理;而${}是直接替换
2.使用不同:#{}适用于所有类型的参数匹配;但 ${}只适用于数值类型。
3.安全性不同:#{}安全性能高,没有安全问题;但 ${}存在SQL注入的安全问题。
虽然${}占位符的使用受限,但是其也有它无可替代的使用场景,当传递的是一个SQL关键字(SQL命令)的时候,只能使用 ${},此时如果使用#{}就会认为传递的为一个普通的值,而非SQL命令,所以执行就会报错。
就像下边这个例子,会有价格从低到高或者从高到低的排序,如果想要实现这样的效果,就需要使用到${}占位符
代码示例:
测试:
下边通过一个登录的案例来引入SQL注入的问题:
我们可以发现,当我输入的密码为' or 1='1
时,经过拼装出来的SQL是select * from userinfo where username='admin' and password='' or 1='1'
,这样即使不知道密码,也能返回该用户的信息,这就是SQL注入问题。
要想解决${}参数占位符带来的SQL注入问题,就需要在业务层对传递的值进行安全效验,如4.1.2中的排序,就需要规定传入的参数只能为asc
或者desc
,也就是说想要用 ${}参数占位符,需要该位置的参数是可穷举的,那么这个4.1.3中登录的例子也就不适用了,所以其更适用于用#{}
来解决登录的问题。
可以发现用#{}
参数占位符去搜索时,查询不到结果,也就解决了该安全隐患。
这是一个特殊的查询,如果使用#{}会报错,但使用${}在业务层的值又不能穷举,就需要通过SQL中的concat
函数,将%
与模糊字符合并起来,如下所示。
如果是增、删、改操作,返回受影响的行数,那么在mapper.xml
中是可以不设置返回的类型的,如下图所示:
但即使如果是最简单的查询操作,也需要设置返回类型,否则就会报错。也就是说对于< select >查询标签来说,至少需要两个属性:
绝大多数查询场景可以使用resultType
进行返回,如下代码所示:
其优点是使用方便,直接定义到某个实体类即可。
resultMap使用场景:
resultMap
配置映射;resultMap
映射并查数据单元测试代码:
单元测试结果:
查询不到name
属性,这时候就需要用到resultMap
了,resultMap
的使用如下:
在多表查询时,如果使用resultType
标签,在一个类中包含了另一个对象,是查询不出来被包含的对象的,比如以下实体类:一篇文章对应一个作者,文章实体类中包含对象实体。
mapper.xml
代码如下:
测试代码如下:
测试结果:
此时,我们就需要使用特殊的手段来实现联表查询了。
一对一映射要使用< association >标签,具体实现如下(一篇文章只对应一个作者):
以上使用< association >标签,表示一对一的结果映射:
映射的mapper.xml
文件如下:
测试代码如下:
测试结果:
一对多需要使用< collection >标签,用法和< association >相同,如下所示:(一个用户对应多篇文章)
测试结果:
我们在进行注册功能时,可能涉及到必填字段和非必填字段两类字段,那如果在添加用户的时候,有不确定的字段传入,程序此时就应该使用动态标签< if >来判断了,该标签的主要作用是判断一个参数是否有值,如果没值,那么会隐藏if中的SQL,如下的photo
字段。
拼装的SQL就会根据是否传入了photo
参数来确定是否增添photo
字段。
之前的插入用户功能,只有一个photo
字段可能是选填项,如果所有字段都是非必填项,就考虑使用< trim >标签结合< if >标签,对多个字段都采取动态生成的方式。最主要的作用就是:去除SQL语句前后多余的某个字符
该标签的主要作用是:
实现查询中的where SQL替换,如果没有任何的查询条件,那么它可以隐藏查询查询中的where SQL,但如果存在查询条件,那么就会生成where的SQL查询;并且使用where标签可以自动的去除最前面的一个and
字符
mapper.xml
中的代码如下:
测试结果:
以上< where >标签也可以使用< trim prefix="where" prefixOverrides="and" >
替换。
该标签的主要作用是:
进行修改操作时,配合if
来处理非必传参数,它的特点是会自动去除最后一个英文逗号。
mapper.xml
中的代码如下:
测试及测试结果如下:
以上< set >标签也可以使用< trim prefix="set" suffixOverrides="," >
替换
对集合进行遍历时可以使用该标签。< foreach >标签有如下属性:
⭐️最后的话⭐️
总结不易,希望uu们不要吝啬你们的哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正