|
|
|
|
MyBatis的底层操作封装了JDBC的API,MyBatis的工作原理以及核心流程与JDBC的使用步骤一脉相承,MyBatis的核心对象(SqlSession,Executor)与JDBC的核心对象(Connection,Statement)相互对应。从JDBC入手并立足于JDBC,才能深入的理解MyBatis的工作原理以及核心流程。
|
|
|
|
|
|
|
|
|
|
# 一、Mybatis工作原理
|
|
|
|
|
JDBC有四个核心对象:
|
|
|
|
|
(1)DriverManager,用于注册数据库连接
|
|
|
|
|
(2)Connection,与数据库连接对象
|
|
|
|
|
(3)Statement/PrepareStatement,操作数据库SQL语句的对象
|
|
|
|
|
(4)ResultSet,结果集或一张虚拟表
|
|
|
|
|
|
|
|
|
|
而MyBatis也有四大核心对象:
|
|
|
|
|
(1)SqlSession对象,该对象中包含了执行SQL语句的所有方法【1】。类似于JDBC里面的Connection 【2】。
|
|
|
|
|
(2)Executor接口,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。类似于JDBC里面的Statement/PrepareStatement。
|
|
|
|
|
(3)MappedStatement对象,该对象是对映射SQL的封装,用于存储要映射的SQL语句的id、参数等信息。
|
|
|
|
|
(4)ResultHandler对象,用于对返回的结果进行处理,最终得到自己想要的数据格式或类型。可以自定义返回类型。
|
|
|
|
|
|
|
|
|
|
在JDBC中,Connection不直接执行SQL方法,而是利用Statement或者PrepareStatement来执行方法。在使用JDBC建立了连接之后,可以使用Connection接口的createStatement()方法来获取Statement对象,也可以调用prepareStatement()方法获得PrepareStatement对象,通过executeUpdate()方法来执行SQL语句。而在MyBatis中,SqlSession对象包含了执行SQL语句的所有方法,但是它是委托Executor执行的。从某种意义上来看,MyBatis里面的SqlSession类似于JDBC中的Connection,他们都是委托给其他类去执行。
|
|
|
|
|
|
|
|
|
|
虽然SqlSession对象包含了执行SQL语句的所有方法,但是它同样包括了:
|
|
|
|
|
```java
|
|
|
|
|
<T> T getMapper(Class<T> type);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
所以SqlSession也可以委托给映射器来执行数据的增删改查操作。如下代码所示:
|
|
|
|
|
```java
|
|
|
|
|
// 获得mapper接口的代理对象
|
|
|
|
|
PersonMapper pm = session.getMapper(PersonMapper.class);
|
|
|
|
|
// 直接调用接口的方法,查询id为1的Peson数据
|
|
|
|
|
Person p2 = pm.selectPersonById(1);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
# 二、MyBatis的工作原理以及核心流程详解
|
|
|
|
|
Mybatis的运行过程分为两大步:
|
|
|
|
|
- 第1步,读取配置文件缓存到Configuration对象,用于创建SqlSessionFactory;
|
|
|
|
|
- 第2步,SqlSession的执行过程。相对而言,SqlSessionFactory的创建还算比较容易理解,而SqlSession的执行过程就不那么简单了,它包括许多复杂的技术,要先掌握反射技术和动态代理,这里主要用到的是JDK动态代理。
|
|
|
|
|
```java
|
|
|
|
|
public class TestMybatis {
|
|
|
|
|
public static void main(String[] args) {
|
|
|
|
|
String resource = "mybatis-config.xml";
|
|
|
|
|
Reader reader = null;
|
|
|
|
|
try {
|
|
|
|
|
reader = Resources.getResourceAsReader(resource);
|
|
|
|
|
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
|
|
|
|
|
SqlSession session = sqlSessionFactory.openSession();
|
|
|
|
|
UserMapper mapper = session.getMapper(UserMapper.class);
|
|
|
|
|
User user = mapper.findById(2);
|
|
|
|
|
System.out.println("name:" + user.getName());
|
|
|
|
|
session.close();
|
|
|
|
|
SqlSession session1 = sqlSessionFactory.openSession();
|
|
|
|
|
List<User> users = session1.selectList("findAll");
|
|
|
|
|
session1.commit();
|
|
|
|
|
System.out.println("allSize:" + users.size());
|
|
|
|
|
session1.close();
|
|
|
|
|
} catch (IOException e) {
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## 2.1 mybatis 的主要构件
|
|
|
|
|
从MyBatis代码实现的角度来看,MyBatis的主要的核心部件有以下几个:
|
|
|
|
|
- SqlSession 作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增改查功能
|
|
|
|
|
- Executor MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护
|
|
|
|
|
- StatementHandler 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合。
|
|
|
|
|
- ParameterHandler 负责对用户传递的参数转换成JDBC Statement 所需要的参数,
|
|
|
|
|
- ResultSetHandler 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合;
|
|
|
|
|
- TypeHandler 负责java数据类型和jdbc数据类型之间的映射和转换
|
|
|
|
|
- MappedStatement MappedStatement维护了一条<select|update|delete|insert>节点的封装,
|
|
|
|
|
- SqlSource 负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
|
|
|
|
|
- BoundSql 表示动态生成的SQL语句以及相应的参数信息
|
|
|
|
|
- Configuration MyBatis所有的配置信息都维持在Configuration对象之中。
|
|
|
|
|
|
|
|
|
|
![[Snipaste_2023-03-02_11-05-25 1.png]]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 2.2 mybatis 执行过程
|
|
|
|
|
![[1745215-20201204225139159-906801326 1.png]]
|