## 概述
MyBatis 是一款优秀的半自动化的持久层框架,支持定制化 SQL、存储过程以及高级映射,避免了几乎所有 JDBC 代码和手动设置参数以及获取结果集,MyBatis 可以使用简单的 xml 或注解用于配置映射,将接口和 Java 的 POJO(Plain Old Java Object,普通 Java 对象)映射成数据库中的记录。
MyBatis 将 SQL 与 Java 代码解耦,写在 映射文件中,而不是硬编码在 Java 代码中,功能边界清晰,维护方便,利于 SQL 的修改与优化
## 使用 MyBatis
### 1. 导入依赖
使用 MyBatis 需要两个核心依赖
```xml
org.mybatis
mybatis
3.5.5
mysql
mysql-connector-java
5.1.47
```
### 2. 创建表以及对应的实体类
在 MySQL 中建一张用于测试用的 `User` 表
```sql
CREATE DATABASE mybatis CHARSET utf8;
USE mybatis;
CREATE TABLE USER (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(11),
PASSWORD VARCHAR(11)
)
```
对应实体类
```java
package cool.yzt.entity;
public class User {
private int id;
private String username;
private String password;
/*
setter、getter、toString
*/
}
```
### 3. 主配置文件
MyBatis 的主配置文件或称全局配置文件,主要是设置 MyBatis 的属性信息,例如运行环境、事务管理、数据库连接池等,指导 MyBatis 正常工作
首先引入约束
```xml
```
主配置
```xml
```
### 4. 映射文件
SQL 映射文件的作用就是相当于定义 DAO 接口的实现类中的代码,一张表对应一个 Mapper 文件,其中定义了对于这张表的增删改查操作,并且 MyBatis 会自动完成数据封装
首先引入约束
```xml
```
作为配置文件,在开发时应该放置在 resources 目录下,并且独立设置一个包,一般命名为 mapper,mapper 包的目录应与 dao 包同级,编译后,mapper 包就会原封不动放置在项目 classes 目录下,与 dao 包同级,下面编写映射文件
```xml
insert into User (username,password) value(#{username},#{password})
update user set password=#{password} where username=#{username}
delete from user where id=#{id}
```
**注意**
1. 如果入参是一个自定义的 POJO,例如 `cool.yzt.entity.User`,则在 sql 中占位符 `#{}` 中的参数可以直接填写该 POJO 中的属性名
2. 如果入参是 Java 原生类型,例如 `java.lang.Integer`,则在 sql 中占位符 `#{}` 中的参数名可以是任意字符,只要保证唯一即可
### 5. 主配置文件中注册 Mapper
在主配置文件中,添加 `` 标签,注册响应的映射文件,注意,此处因为要写 xml 文件的后缀名,所以前面包名之间使用 `/` 隔开
```xml
```
### 6. 调用 MyBtis 的原生 API,测试使用
为简单,这里直接使用单元测试,且使用 MyBtis 的原生 API,而不是编写相应的 dao 接口,使用 MyBatis 完成对数据库的增删改查,需要以下几步
1. 创建 `SqlSessionFactoryBuilder` 对象
```java
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
```
2. 通过 `SqlSessionFactoryBuilder` 的 `build()` 方法创建 `SqlSessionFactory`,并以流的形式传入配置文件
```java
InputStream is = MyBatisTest.class.getClassLoader().getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = builder.build(is);
```
3. 通过 `SqlSessionFactory` 获取 `SqlSession` 对象,一个 `SqlSession` 对象代表与数据库的一次会话
```java
SqlSession sqlSession = factory.openSession();
```
4. 调用 `SqlSession` 的相应方法,完成增删改查,注意,MyBatis 要手动提交事务(增删改)
```java
// 插入数据,第一个参数是Mapper文件的namespace + 相应的sql的id标识,第二个参数就是 parameterType中的参数类型
sqlSession.insert("UserMapper.save",new User());
sqlSession.commit();
// 查找数据,使用 List 接收返回参数
List list = sqlSession.selectList("UserMapper.findAll");
// 修改数据
sqlSession.update("UserMapper.update",user);
sqlSession.commit();
// 删除数据
sqlSession.delete("UserMapper.deleteById",3);
sqlSession.commit();
```
5. 关闭 `SqlSession`,非常重要的一步,不可缺少
```java
sqlSession.close();
```
## MyBtis 面向接口编程
以上使用 MyBtis 原生 API 是 MyBtis 老版本完成增删改查的方式,现在 MyBtis 推荐使用接口的方式,即编写一个 DAO 接口,并且在 Mapper 文件中与相应的接口进行绑定,具体实现如下
1. 编写一个 `UserMapper` 接口
```java
package cool.yzt.dao;
import cool.yzt.entity.User;
import java.util.List;
public interface UserMapper {
public void save(User user);
public List findAll();
public void changePassword(User user);
public void delete(Integer id);
}
```
2. 修改对应的 Mapper 文件,其中 Mapper 的 `namespace` 为对应接口的全类名,Statement 的 `id` 为对应接口中对应方法的方法名,`parameterType` 和 `resultType` 的类型都与接口的参数和返回值类型相同,如此便可将一个 DAO 层的接口与一个映射文件中的 Statement(定义了具体的 sql)进行绑定
```xml
insert into User (username,password) value(#{username},#{password})
update user set password=#{password} where username=#{username}
delete from user where id=#{id}
```
3. 通过 `SqlSession` 获取 MyBatis 为该 DAO 接口创建的代理实现类对象,如此,Service 层就可以通过该实现类的对象调用接口中的方法完成增删改查
```java
@Test
public void test() {
// 获取 SqlSession
InputStream is = MyBatisTest.class.getClassLoader().getResourceAsStream("mybatis.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
// 获取接口的实现类对象,这个对象是 MyBatis 通过动态代理生成的实现类的对象
UserDao mapper = session.getMapper(UserMapper.class);
// 通过实现类对象调用接口的方法
try {
List users = mapper.findAll();
for(User user : users) {
System.out.println(user);
}
} finally {
session.close();
}
}
```
**注意**
1. 我们并没有手动为 DAO 接口写一个实现类,而是由 MyBatis 框架自动生成一个代理实现类对象
2. 这种面向接口的方式使用 MyBatis,可以建立一种 DAO 层的规范,屏蔽具体实现,也就是说,DAO 接口的实现可以使用 MyBatis,也可以使用其他 DAO 层框架或原生 JDBC,对 sql 的优化也是在映射文件中修改,无需修改代码,方便维护
3. Service 层调用的方法都来自 DAO 接口中规定好的,可以更安全的对参数和返回值进行类型检查
4. `SqlSession` 是非线程安全的,相当于 `Connection`,对于数据库的每一次访问都需要创建新的 `SqlSession`,且最后必须正确关闭
5. `SqlSessionFactory` 对象是一个重量级对象,一个应用只需创建一次
## 参考
[尚硅谷 MyBatis 教程](https://www.bilibili.com/video/BV1zb411V77d)

MyBatis 入门