mybatis原理解析
Mybatis 整体执行流程
Mybatis 具体流程源码分析
分析Mybatis 的执行流程
public class MybatisTest {
public static void main(String[] args) throws IOException {
//1. 读取mybatis-config.xml 文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
//2. 构建SqlSessionFactory(创建了DefaultSqlSessionFactory)
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//3. 打开SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//4. 获取Mapper 接口对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//5. 获取mapper 接口对象的方法操作数据库
List<SysUser> sysUsers = mapper.selectByIdList(Arrays.asList(1L));
System.out.println("查询结果为:" + sysUsers.size());
}
}
源码分析
创建SqlSessionFactory
先new一个SqlSessionFactoryBuilder,然后调用他的build方法,创建一个SqlSessionFactory工厂,其核心思想就是把mybatis-config.xml和所有mapper.xml文件解析,然后封装到Configuration对象中。Configuration对象包含了我们在配置文件中配置的信息
创建SqlSession
SqlSession的获取主要是通过SqlSessionFactory的默认实现类DefaultSqlSessionFactory中的openSessionFromDataSource方法封装一个DefaultSqlSession(DefaulSqlSession是SqlSession的实现类)返回。
会创建SqlSession的执行器。在 Mybatis 配置⽂件中,可以指定默认的 ExecutorType 执⾏器类型,也可以⼿动给DefaultSqlSessionFactory 的创建 SqlSession 的⽅法传递 ExecutorType 类型参数。mybatis整体是用sqlsession作为门面模式,在底层实际负责去执行的是executor.
一个SqlSession对应一个Executor ,Executor限制在 SqlSession ⽣命周期范围内。
关于 ExecutorType 有三种类型:
- SimpleExecutor是一种常规执行器,每次执行都会创建一个statement,用完后关闭。
- ReuseExecutor是可重用执行器,将statement存入map中,操作map中的statement而不会重复创建statement。
- BatchExecutor是批处理型执行器,doUpdate预处理存储过程或批处理操作,doQuery提交并执行过程。【执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。】
获取Mapper接口的实现类对象
Configuration中的mapperRegistry,已经保存了UserMapper的Class对象,接下来就是用JDK自带的动态代理生成UserMapper的代理对象,通过动态代理生成代理对象直接调用对应的方法,避免程序中的硬编码。
调用mapper接口的方法时的处理
在getMapper的代理实现中引入SqlSession,通过调用对应增删改查实现数据库操作
Mybatis 核心组件
组件名 | 功能 |
---|---|
Configuration | Mybatis 所有的配置信息都维持在Configuration 对象之中 |
SqlSession | 作为Mybatis 工作的主要顶层API,表示和数据库交互的会话,完成数据库增删查改功能 |
Executor | Mybatis 执行器,是Mybatis 调度的核心,负责SQL |
StatementHandler | 封装了JDBC Statement 操作,负责对JDBC statement 的操作,如设置参数,将 Statement 结果集转换为List 集合 |
ParameterHandler | 负责对用户传递的参数转换为JDBC Statement 所需要的参数 |
ResultSetHandler | 负责将JDBC返回的ResultSet结果集对象转换为List 类型的集合 |
MappedStatement | MappedStatement 维护了一条select语句 |
MapperProxy,MapperProxyFactory | Mapper 代理,使用原生的Proxy 执行mapper 里的方法 |
Mybatis 使用到的设计模式
Builder 模式 : SQLSessionFactoryBuilder、Environment
- 在Mybatis 环境的初始化过程中,SqlSessionFactoryBuilder 会调用XMLConfigBuilder 读取 mybatis-config.xml 和所有的 *Mapper.xml 文件,构建Mybatis 核心对象 Configuration ,然后将Configuration 对象作为参数构建一个 SqlSessionFactory。在这个过程中,Builder 会读取文件或配置,然后做XpathParser 解析,配置或语法解析,反射生成对象,存入结果缓存等步骤,这么多的工作不是一个构造函数所能包括的,因此大量采用了Builder 模式来解决。
工厂模式 :SqlSessionFactory、TransactionFactory、LogFactory
- 在Mybatis 中使用了简单工厂模式,因为没有什么复杂的业务逻辑。Mybatis 中执行sql 语句、获取Mappers、管理事务的核心接口SqlSession 的创建过程使用到了工厂模式,有一个SqlSessionFactory 来负责 SqlSession 的创建。
单例模式 : ErrorContext、LogFactory
代理模式 :Mybatis 实现核心,比如MapperProxy、ConnectionLogger
- 代理模式可以认为是Mybatis 核心使用模式,正式由于这个模式,我们只需要编写Mapper 接口,不需要实现,由Mybatis 后台帮我们完成具体SQL 的执行。当我们使用Configuration 的getMapper 方法时,会调用mapperRegistry.getMapper 方法,而该方法又会调用mapperProxyFactory.newInstance(sqlSession)来生成一个具体的代理。
模板方法模式 :BaseExecutor、SimpleExecutor、BaseTypeHandler 和其子类
适配器模式 :Log 的Mybatis 接口和它对jdbc、log4j