什么是MyBatis
MyBatis是⼀款优秀的 持久层 框架,⽤于简化JDBC的开发。
MyBatis本是 Apache的⼀个开源项⽬iBatis,2010年这个项⽬由apache迁移到了google code,并
且改名为MyBatis 。2013年11⽉迁移到Github
创建项目时添加依赖

上面有提到⼀个词:持久层
持久层:指的就是持久化操作的层, 通常指数据访问层(dao), 是⽤来操作数据库的.
简单来说 MyBatis 是更简单完成程序和数据库交互的框架,也就是更简单的操作和读取数据库工具
MyBatis⼊⻔
Mybatis操作数据库的步骤:

准备⼯作
创建⼯程
创建springboot⼯程,并导⼊ mybatis的起步依赖、mysql的驱动包
Mybatis 是⼀个持久层框架, 具体的数据存储和数据操作还是在MySQL中操作的, 所以需要添加
MySQL驱动
项⽬⼯程创建完成后,⾃动在pom.xml⽂件中,导⼊Mybatis依赖和MySQL驱动依赖
版本会随着SpringBoot 版本发⽣变化
SpringBoot 3.X对⽤MyBatis版本为3.X
对应关系参考: https://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/
数据准备
创建⽤⼾表, 并创建对应的实体类User
创建对应的实体类 UserInfo
实体类的属性名与表中的字段名⼀⼀对应,一模一样
配置数据库连接字符串
注意事项:
如果使⽤ MySQL 是 5.x 之前的使⽤的是"com.mysql.jdbc.Driver",如果是⼤于 5.x 使⽤的 是"com.mysql.cj.jdbc.Driver".
写持久层代码


单元测试





@SpringBootTest就是一个将运行环境交给这个测试类的注解,没有这个注解,就没法注入依赖这些操作,因为被管理的依赖都是在运行环境里的。
MyBatis的基础操作
上⾯使用了Mybatis的查询操作, 接下来学习MyBatis的增, 删, 改操作
在学习这些操作之前, 我们先来学习MyBatis⽇志打印
打印⽇志
在Mybatis当中我们可以借助⽇志, 查看到sql语句的执⾏、执⾏传递的参数以及执⾏结果
在配置⽂件中进⾏配置即可
重新运⾏程序, 可以看到SQL执⾏内容, 以及传递参数和执⾏结果
参数传递
需求: 查找id=4的⽤⼾,对应的SQL就是: select * from user_info where id=4
但是这样的话, 只能查找id=4 的数据, 所以SQL语句中的id值不能写成固定数值,需要变为动态的数值
解决⽅案:在queryById⽅法中添加⼀个参数(id),将⽅法中的参数,传给SQL语句
使⽤ #{} 的⽅式获取⽅法中的参数

如果mapper接⼝⽅法形参只有⼀个普通类型的参数,#{...} ⾥⾯的属性名可以随便写,如:#{id}、# {value}。需要和参数名保持一样,不然没法成功传参,或者使用注解标识参数名。顺序不重要,参数名对的上就行。但是如果只传递一个参数,参数名就不需要对上,因为只有一个参数也没得选,但是最好还是参数名和#{}里的名称对上。
不建议使用方法:
使用paramN在#{}里,这个代值第n个参数。
如果只查询0-1个表当中的数据来赋值给实体类,那么返回值为实体类就行了,没查询到会返回null。如果返回多个数据却用实体类接收会报异常。
如果是查询0-n个数据,就需要将返回值设置为List<T>T是实体类,没查询到会返回null。
如果返回值为基础类型,不是包装类没有查询到数据,返回值可能会有逻辑错误,所以只查询一个基础类型的话推荐使用包装类,包装了的话没有查询到返回null。
list来接受数据库给的返回值是因为,这样就不需要关心数据库具体返回的类型是什么arraylist 还是linklist,只需要知道是一个list类型,来通过多态就可以调用list通用的方法了。
增(Insert)

也可以将传递的参数直接改成传递对象,对象里的属性名和类型也是要一一对应的。

返回主键
Insert 语句默认返回的是受影响的⾏数,这些mysql语句的返回值和在数据库直接调用的返回值是一样的。
但有些情况下, 数据插⼊之后, 还需要有后续的关联操作, 需要获取到新插⼊数据的id
⽐如订单系统
当我们下完订单之后, 需要通知物流系统, 库存系统, 结算系统等, 这时候就需要拿到订单ID
如果想要拿到⾃增id, 需要在Mapper接⼝的⽅法上添加⼀个Options的注解

这个自增id会被赋值到传递的对象里面,通过getid来获得。


删(Delete)

改(Update)

查(Select)



可以看到,mysql的属性写法是下划线写法,而java类当中的写法是小驼峰写法。

起别名

结果映射



开启驼峰命名

mybatis:
configuration:
map-underscore-to-camel-case: true # 配置驼峰⾃动转换


MyBatis XML配置文件
Mybatis的开发有两种⽅式:
注解
XML
上⾯学习了注解的⽅式, 接下来我们学习XML的⽅式
使⽤Mybatis的注解⽅式,主要是来完成⼀些简单的增删改查功能. 如果需要实现复杂的SQL功能,建议使⽤XML来配置映射语句,也就是将SQL语句写在XML配置⽂件中.
MyBatis XML的⽅式需要以下两步:
配置数据库连接字符串和MyBatis
写持久层代码
配置连接字符串和MyBatis和写持久层代码的⽅法定义 Interface和使用注解来完成数据库交互的步骤是一样的,除了还要设置MyBatis的XML的文件设置,配置xml文件的扫描路径。
配置连接字符串和MyBatis


# 配置 mybatis xml 的⽂件路径,在 resources/mapper 创建所有表的 xml ⽂件
10 mybatis.mapper-locations = classpath:mapper/**Mapper.xml
mybatis:
10 mapper-locations: classpath:mapper/**Mapper.xml
写持久层代码

添加 mapper 接口
注解和xml定义的接口不需要另外实现,用注解和xml就自动实现了。
添加 UserInfoXMLMapper.xml
数据持久成的实现,MyBatis 的固定 xml 格式
<?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.UserInfoMapper">//这个定义的是要实//现的类的路径
</mapper>
<?xml version="1.0" encoding="UTF-8"?>
作用:这是 XML 文件的声明部分,用于定义 XML 的版本和字符编码。
解释:
version="1.0" :指定 XML 文档遵循的 XML 1.0 规范,是目前最基础、通用的 XML 版本。
encoding="UTF-8" :设置 XML 文件的字符编码为 UTF-8,确保文件能正确解析中文字符等特殊字符,避免乱码问题。
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
作用:定义 XML 的文档类型(DTD,Document Type Definition),用于约束 Mapper XML 的结构和语法。
解释:
<!DOCTYPE mapper ... > :声明这是一个 MyBatis 的 mapper 类型文档。
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" :表示这是 MyBatis 官方定义的公共 DTD, 3.0 是 DTD 的版本, EN 表示语言为英文。
http://mybatis.org/dtd/mybatis-3-mapper.dtd :指定 DTD 文件的位置,MyBatis 解析器会通过该 URL 验证 XML 内容是否符合 Mapper 文件的语法规则(如标签、属性是否合法)。
<mapper namespace="com.example.demo.mapper.UserInfoMapper">
作用:定义 Mapper 的命名空间(namespace),是 MyBatis 中非常关键的配置。
解释:
namespace 的值通常与对应的 Mapper 接口全类名一致(如这里的 com.example.demo.mapper.UserInfoMapper ,假设存在同名 Java 接口)。
作用:
绑定接口:MyBatis 会通过命名空间关联对应的 Mapper 接口,接口中的方法与 XML 中 <select> 、 <insert> 等标签的 id 一一映射,实现接口方法到 SQL 的关联。
避免 SQL 冲突:不同 Mapper XML 中即使有相同 id 的 SQL 标签,只要命名空间不同,就不会冲突,保证 SQL 定义的唯一性。
返回的数据类型是实体类的类型,而不是List<T>这样的,要的是返回所包含的类型。
增(Insert)
UserInfoMapper接⼝:
xml格式,可以随意的换行,还是视为同一条指令的。

删(Delete)

改(Update)

查(Select)




resultType换成了resultMap
这个映射可以多次使用

其他查询操作
多表查询
多表查询和单表查询类似, 只是SQL不同⽽已
准备⼯作
上⾯建了⼀张⽤⼾表, 我们再来建⼀张⽂章表, 进⾏多表关联查询.
⽂章表的uid, 对应⽤⼾表的id.




多表查询实际上和单表查询没有区别,需要的是创建另外的实体类,能够接收查询到的数据,虽然可以直接包含其他的实体类,但建议还是另外加上基础类型。
多表查询的问题
实际开发中最好不要用多表查询,因为这会导致一种慢查询的现象,在mysql查询中,每一个查询都需要mysql线程池中的一个线程,多表查询的时间必然比单表查询要慢,那么就会导致占有线程的时间过长,导致其他业务不能及时的得到处理,这是非常致命的。所以建议还是将多表查询细分为单表查询,再通过程序员自身将单表查询到的数据串联起来,能够有效的提升查询效率,并且还能通过索引优化。

就像这里一样,多表查询是同时查询两张表并且将两张表的数据段进行比较,而两个单表查询就可以先查询出其中一张表的id,再通过这张表的id作为另外一张表的关联字段 user_id这种作为where的查询条件,就可以加快查询速度。
#{} 和 ${}
MyBatis 参数赋值有两种⽅式, 咱们前⾯使⽤了 #{} 进⾏赋值, 接下来我们看下⼆者的区别
#{} 和 ${}区别





结果依然被正确查询出来了, 其中参数 or被当做了SQL语句的⼀部分,这是一种很危险的情况,代表了不需要密码就可以直接访问数据库的数据。
排序功能

${}可以在那些参数较少,受限制,能够校验的场景下使用。

此之外, 还有表名作为参数时, 也只能使⽤ ${}。
因为有时会有数据量过大,从而导致需要分表分库的情况。
like 查询

数据库连接池
在上⾯Mybatis的讲解中, 我们使⽤了数据库连接池技术, 避免频繁的创建连接, 销毁连接
下⾯我们来了解下数据库连接池
数据库连接池负责分配、管理和释放数据库连接,它允许应⽤程序重复使⽤⼀个现有的数据库连接,⽽不是再重新建⽴⼀个
学习⽂档: https://github.com/alibaba/druid/wiki/%E9%A6%96%E9%A1%B5
总结
MySQL 开发企业规范

#{} 和${} 区别
