/images/avatar.png

Mybatis3源码分析(5)spring集成分析与mybatis所用到的设计模式

这里我们以传统的 Spring 为例,因为配置更直观,在 Spring 中使用配置类注解是一样的。在前面文章里面,我基于编程式的工程已经弄清楚了 MyBatis 的工作流程、核心模块和底层原理。编程式的工程,也就是 MyBatis 的原生 API 里面有三个核心对象: SqlSessionFactory、SqlSession、MapperProxy 大部分时候我们不会在项目中单独使用 MyBatis 的工程,而是集成到 Spring 里面使用,但是却没有看到这三个对象在代码里面的出现。我们直接注入了一个 Mapper 接口,调用它的方法。 所以有几个关键的问题,我要弄清楚:

  1. SqlSessionFactory 是什么时候创建的?
  2. SqlSession 去哪里了?为什么不用它来 getMapper?
  3. 为什么@Autowired 注入一个接口,在使用的时候却变成了代理对象?在 IOC的容器里面我们注入的是什么? 注入的时候发生了什么事情?

Mybatis3源码分析(4)插件分析

源码总结回顾

{% raw %}

对象相关对象作用
ConfigurationMapperRegistry TypeAliasRegistry TypeHandlerRegistry包含了 MyBatis 的所有的配置信息
SqlSessionSqlSessionFactory DefaultSqlSession对操作数据库的增删改查的 API 进行了封装,提供给应用层使用
ExecutorBaseExecutor SimpleExecutor BatchExecutor ReuseExecutorMyBatis 执行器,是 MyBatis 调度的核心,负责 SQL 语句的生成和查 询缓存的维护
StatementHandlerBaseStatementHandler SimpleStatementHandler PreparedStatementHandler CallableStatementHandler封装了 JDBC Statement 操作,负责对 JDBC statement 的操作,如设 置参数、将 Statement 结果集转换成 List 集合
ParameterHandlerDefaultParameterHandler把用户传递的参数转换成 JDBC Statement 所需要的参数
ResultSetHandlerDefaultResultSetHandler把 JDBC 返回的 ResultSet 结果集对象转换成 List 类型的集合
MapperProxyMapperProxyFactory代理对象,用于代理 Mapper 接口方法
MappedStatementSqlSource BoundSqlMappedStatement 维护了一条select|update|delete|insert节点 的封装,包括了 SQL 信息、入参信息、出参信息
{% endraw %}

插件拦截的四大对象

{% raw %}

对象描述可拦截的方法方法作用
Executor上层的对象,SQL 执行全过程,包括组装参数,组装结果集返回和执行 SQL 过程update执行 update、insert、delete 操作
query执行 query 操作
flushStatements在 commit 的时候自动调用,SimpleExecutor ReuseExecutor、BatchExecutor 处理不同
commit提交事务
rollback事务回滚
getTransaction获取事务
close结束(关闭)事务
isClosed判断事务是否关闭
StatementHandler上层的对象,SQL 执行全过程,包括组装参数,组装结果集返回和执行 SQL 过程prepare(BaseSatementHandler)SQL 预编译
parameterize设置参数
batch批处理
update增删改操作
query查询操作
ParameterHandlerSQL 参数组装的过程getParameterObject获取参数
setParameters设置参数
ResultSetHandler结果的组装handleResultSets处理结果集
handleOutputParameters处理存储过程出参
{% endraw %}

Mybatis3源码分析(2)体系结构与缓存

工作流程分析

  • 首先在 MyBatis 启动的时候我们要去解析配置文件,包括全局配置文件和映射器配置文件,这里面包含了我们怎么控制 MyBatis 的行为,和我们要对数据库下达的指令,也就是我们的 SQL 信息。我们会把它们解析成一个 Configuration 对象。
  • 接下来就是我们操作数据库的接口,它在应用程序和数据库中间,代表我们跟数据库之间的一次连接:这个就是 SqlSession 对象。
  • 我们要获得一个会话,必须有一个会话工厂SqlSessionFactory。SqlSessionFactory 里面又必须包含我们的所有的配置信息,所以我们会通过一个Builder 来创建工厂类。
  • 我们知道,MyBatis 是对 JDBC 的封装,也就是意味着底层一定会出现 JDBC 的一些核心对象,比如执行 SQL 的 Statement,结果集 ResultSet。在 Mybatis 里面,SqlSession 只是提供给应用的一个接口,还不是 SQL 的真正的执行对象。
  • 我们上次课提到了,SqlSession 持有了一个 Executor 对象,用来封装对数据库的操作。在执行器 Executor 执行 query 或者 update 操作的时候我们创建一系列的对象,来处理参数、执行 SQL、处理结果集,这里我们把它简化成一个对象:StatementHandler, 在阅读源码的时候我们再去了解还有什么其他的对象。

流程图

https://yakax.oss-cn-hangzhou.aliyuncs.com/blog/2019-06-04/1.png

Mybatis3源码分析(1)生命周期与核心配置解读以及批量操作

单独用mybatis编程式进行DB操作

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
--------------------利用mapper
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
try {
    BlogMapper mapper = session.getMapper(BlogMapper.class);
    Blog blog = mapper.selectBlogById(1);
    System.out.println(blog);
} finally {
    session.close();
}
--------------------利用mybatis的接口
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession(); // ExecutorType.BATCH
try {
    Blog blog = (Blog) session.selectOne("com.yakax.mapper.BlogMapper.selectBlogById", 1);
    System.out.println(blog);
} finally {
    session.close();
}