mybatis

    • 配置环境
    • 实现查询功能:
    • MyBatisX插件
    • 条件查询
      • $和#区别
      • $ sql注入情况:
      • $的好处:
    • 修改密码操作
    • 删除操作
    • 添加
    • 模糊查询
    • 返回字典映射
    • 多表查询

配置环境

分两种情况;1:已经创建的项目进行mybaits升级;2:在新项目里进行mybatis装配。

1:添加MyBatis框架支持(上述两种情况都需要这步操作)
因为底层还是jdbc;我们用的是MySQL;添加MySQL Driver、MyBatis Framework
mybatis_第1张图片
2:配置文件;连接数据库;映射当前项目路径(classpath);这里固定写法。
mybatis_第2张图片

mybatis.mapper-locations 是用于指定 SQL 映射文件(Mapper 文件)的位置。数据库的操作语句保存在*Mapper.xml。(如果不映射;一大堆SQL文件写在配置文件里不美观;也不解耦)

实现查询功能:

1:添加实体类;

mybatis_第3张图片

2:添加mapper接口
@Mapper 注解的作用是告诉 MyBatis 框架将该接口类视为映射器接口,并为其生成对应的实现类。这个实现类会通过动态代理技术在运行时自动生成,实现了映射器接口中定义的数据库操作方法的具体逻辑。
mybatis_第4张图片

3:添加Mapper的xml文件(这个xml文件名;望文生义即可;并没有强制性要求)
这段代码是固定的;只需要我们中间添加sql语句即可;com.example.demo.mapper.UserMapper对应我们上一步创建的接口的位置。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.demo.mapper.UserMapper">


</mapper>

resultType=“com.example.demo.entity.UserEntity”;表示查询结果将会被映射到 UserEntity 类型的对象中。
id="getAll"是和 Interface(接⼝)中定义的⽅法名称⼀样的,表示用这个sql对接⼝的具体实现⽅法。(底层是jdbc;是用这个sql语句来实现的方法?应该就是)
mybatis_第5张图片

4:添加服务层
mybatis_第6张图片

5:添加控制层(套娃;控制层调用服务层;服务层调用接口里的方法)
mybatis_第7张图片

效果:
mybatis_第8张图片

mybatis_第9张图片

MyBatisX插件

在庞大的项目中能较方便的找位置
mybatis_第10张图片
mybatis_第11张图片

条件查询

测试数据库:

-- 创建数据库
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 '',
    createtime timestamp default current_timestamp,
    updatetime timestamp default current_timestamp,
    `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 timestamp default current_timestamp,
    updatetime timestamp default current_timestamp,
    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 timestamp default current_timestamp,
		updatetime timestamp default current_timestamp,
  	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);

mybatis_第12张图片
mybatis_第13张图片
如果想打印MyBatis执行的SQL;通过日志打印。

mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

mybatis获取动态参数两种实现:直接替换、占位符模式
mybatis_第14张图片
上述传的是普通参数如果要传对象?xml怎么使用这个对象呢?
在这里插入图片描述mybatis_第15张图片
mybatis_第16张图片

$和#区别

当使用 $ 引用参数时,MyBatis 将直接将参数值替换到 SQL 语句中,不会进行预编译或参数绑定。SQL 语句中的参数引用将直接使用参数的字符串表示,不会在运行时进行类型转换或防止 SQL 注入攻击。(不够安全;如果是int类型是没有区别的。String就有区别)

书写问题:
$:比如String类型;你不加引号;它也不会加引号;直接替换过去。select *from videoinfo where title=’ $ {hh} '。如果不加引号;mysql执行的就是select *from videoinfo where title=hh;必然报错title是varchar类型;title='hh’才对(如果换#则不用加引号也行)

安全问题:
在单元测试下;正常是成功查到用户名和密码;以下sql注入不正常的情况也能查询到密码
mybatis_第17张图片

$ sql注入情况:

因为我们当前接收是一条数据;而当前sql注入会返回多条数据;所以当前最好是数据库的这个表里只有一条数据。

mybatis_第18张图片
" ‘or 1=‘1 " :替换后select *from videoinfo where vid=‘1’ and url=’’ or 1=‘1’

mybatis_第19张图片
问题在于;把我的字符串当sql去执行了;如果占位符就不会出现这种情况;占的这个位置就是这个字符串的。

$的好处:

$也有它的好处;当要传的就是一个sql、关键字语句;使用占位符#可不行。 在这里插入图片描述
如果使用#代码都报错。它认为这里是占位符是一个参数去传的。而不是sql的。但是 $有风险;在这种情况我们对前端传过来的参数能进行限制要么是升序、要么是降序,如果传其它就不给你通过;这种处理还是能接受。最好我们还是用#;在服务层;写两份代码;升序则调用升序的代码;降序就调用降序的代码。
mybatis_第20张图片

修改密码操作

返回受影响的行数;因为有可能管理员改多个人(重置密码);张三叫李四改密码。其实原密码可传可不传;因为到这一步骤说明前面已经验证了你的密码是正确的;只需要传新密码即可。
mybatis_第21张图片
mybatis_第22张图片
这个标签select是必须要设置这两个属性;update只需要有interface方法对应就行了;

mybatis_第23张图片

可以看到我们的数据库有这样的数据;单元测试试试可不可行;@Transactional注解在单元测试的效果是不会污染数据库;会进行一个事务的回滚;我们之前也只是查询;并不会对数据库污染;但是修改会;所以需要加这个注解。mybatis_第24张图片

删除操作

在这里插入图片描述

mybatis_第25张图片
这个delete标签也是只需要interface里的方法即可;
mybatis_第26张图片

在这里插入图片描述

添加

添加这里涉及一个问题;是传对象还是参数好?当然是对象;后续要用户表要添加字段只需要改实体类即可
在这里插入图片描述
在这里插入图片描述

mybatis_第27张图片
返回影响的行数以及id:
insert标签:在执行插入操作时,使用数据库自动生成的键值,并将生成的键值存储到名为id的属性中。这个id是源自interface传入对象参数里的实体类属性。
在这里插入图片描述

mybatis_第28张图片
我们前面的数据id是1、2、3;可以看到我们并没有设置这个对象的id值却打印出id为4;因为这个id是来自数据库的;如果你没有给id设置成主键就会报错的。

mybatis_第29张图片

模糊查询

根据用户名进行模糊查询:查询到的结果可能包含多条信息;使用list接收。

在这里插入图片描述
注意:在写模糊查询时需要单引号;select * from 表名 where 列 like ‘%’;而这里占位符;你传的string;它又加了一对单引号;语法报错。构造出来语句:select * from userinfo where username likr ‘% ‘zhang’ %’;
concat函数:拼接作用;不限制参数;想拼接啥都行。concat(‘%’,‘zhang’,‘%’)把这些参数都拼接一块
mybatis_第30张图片
mybatis_第31张图片

返回字典映射

如果遇到实体类和数据库字段如果名字不匹配;那怎么办?数据库的结果没办法映射到你的实体类上。
当我把实体类的属性名改成pwd;其它还是原来的样子;在查找password jdbc已经查到这个对象的内容;但是对比的时候发现pwd!=password;就映射失败。
上述情况使用resultMap:type表示当前字典是要映射哪个实体类。但是这个要一个一个写确实挺麻烦的
mybatis_第32张图片
另一种解决方案:取别名;jdbc返回的是别名
mybatis_第33张图片

多表查询

上述我们解决单表查询的问题;现在来到多表的问题处理。
mybatis_第34张图片
我们可以在实体层上建一个VO(VO是一种用于封装和传输数据的简单对象)存放两个表共同对应的属性

mybatis_第35张图片
mybatis_第36张图片

mybatis_第37张图片

这里得注意一下;lombok的tostring方法是不包含父类属性的;我们自己重写tostring方法;当用lombok后你自己又在代码重写这个方法;那么将会以你的为主。(这里我们可以在生成的.class文件看到)
mybatis_第38张图片
mybatis_第39张图片

select a.*,u.username from articleinfo a left join userinfo u on u.id=a.uid where a.id=#{id}
a. * , u.username: 这是查询的字段列表;from articleinfo a: 这是查询的主要表,指定了主表的别名为"a。left jion userinfo u ON u.id = a.uid: 这是一个左连接(LEFT JOIN)操作,将"articleinfo"表与"userinfo"表进行关联。它基于两个表之间的条件关系进行匹配,具体条件是"userinfo"表中的"id"字段等于"articleinfo"表中的"uid"字段。别名"u"用于引用"userinfo"表。
WHERE a.id = #{id}: 这是一个查询条件,限定了"articleinfo"表中的"id"字段等于给定的参数值"#{id}"。

单元测试效果:
mybatis_第40张图片

你可能感兴趣的:(spring,mybatis,java,mysql)