一、Mybatis的整体架构
Mybatis的架构分为三层:
**接口层:**Mybatis有两种交互方式,一种是通过API方式,这种主要是通过sqlSession来进行操作;另一种是通过Mapper接口来交互,这种是将每个Mapper接口的方法和参数确定一个statementId,底层还是通过sqlSession的方式来执行。
**数据处理层:**数据处理层主要功能的是根据传入的参数动态生成sql,并且做好参数类型的映射,在查询完sql结果后,再将结果包装成List返回。
**框架支持层:**该层主要实现Mybatis的一些特性,包括事务管理、连接池管理、缓存机制等。
Mybatis的主要执行流程:
Mybatis启动过程:解析config.xml–>解析xml映射文件—>每个方法生成mappedStatement–>生成configuration对象
Mybatis执行一句sql流程:sqlSession–>Executor–>StatementHandler(封装了JDBC的操作)–>ParameterHandler–>ResultSetHandler–>TypeHandler–>根据用户的参数结合mappedStatement动态生成BoundSql
二、Mybatis初始化过程
1.配置文件Mybatis-config.xml解析过程
初始化步骤:
- 调用SqlSessionFactoryBuilder对象的build(inputStream)方法;
- SqlSessionFactoryBuilder会根据输入流inputStream等信息创建XMLConfigBuilder对象;
- SqlSessionFactoryBuilder调用XMLConfigBuilder对象的parse()方法;
- XMLConfigBuilder对象返回Configuration对象;
- SqlSessionFactoryBuilder根据Configuration对象创建一个DefaultSessionFactory对象;
- SqlSessionFactoryBuilder返回 DefaultSessionFactory对象给Client,供Client使用。
2.Mapper映射文件解析过程
select方法是最常见的映射方法,其配置也是最复杂的,可以通过resultMap来简化映射的关系。
<select
<!-- 1. id (必须配置)
id是命名空间中的唯一标识符,可被用来代表这条语句。
一个命名空间(namespace) 对应一个dao接口,
这个id也应该对应dao里面的某个方法(相当于方法的实现),因此id 应该与方法名一致
-->
id="selectPerson"
<!-- 2. parameterType (可选配置, 默认为Mybatis自动选择处理)
将要传入语句的参数的完全限定类名或别名, 如果不配置,Mybatis会通过ParameterHandler 根据参数类型默认选择合适的typeHandler进行处理
parameterType 主要指定参数类型,可以是int, short, long, string等类型,也可以是复杂类型(如对象) -->
parameterType="int"
<!-- 3. resultType (resultType 与 resultMap 二选一配置)
resultType用以指定返回类型,指定的类型可以是基本类型,可以是java容器,也可以是javabean -->
resultType="hashmap"
<!-- 4. resultMap (resultType 与 resultMap 二选一配置)
resultMap用于引用我们通过 resultMap标签定义的映射类型,这也是Mybatis组件高级复杂映射的关键 -->
resultMap="personResultMap"
<!-- 5. flushCache (可选配置)
将其设置为 true,任何时候只要语句被调用,都会导致本地缓存和二级缓存都会被清空,默认值:false -->
flushCache="false"
<!-- 6. useCache (可选配置)
将其设置为 true,将会导致本条语句的结果被二级缓存,默认值:对 select 元素为 true -->
useCache="true"
<!-- 7. timeout (可选配置)
这个设置是在抛出异常之前,驱动程序等待数据库返回请求结果的秒数。默认值为 unset(依赖驱动)-->
timeout="10000"
<!-- 8. fetchSize (可选配置)
这是尝试影响驱动程序每次批量返回的结果行数和这个设置值相等。默认值为 unset(依赖驱动)-->
fetchSize="256"
<!-- 9. statementType (可选配置)
STATEMENT,PREPARED 或 CALLABLE 的一个。这会让 Mybatis 分别使用 Statement,PreparedStatement 或 CallableStatement,默认值:PREPARED-->
statementType="PREPARED"
<!-- 10. resultSetType (可选配置)
FORWARD_ONLY,SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 中的一个,默认值为 unset (依赖驱动)-->
resultSetType="FORWARD_ONLY">
三、Mybatis执行一句sql流程
Mybatis是通过sqlSession来和数据库进行通信的,每个sqlSession对应一次数据库会话。sqlSession创建的流程如下:
获取sqlSession的步骤:
- 从Configuration中获取Environment;
- 从Environment中取得DataSource;
- 从Environment中取得TransactionFactory;
- 从DataSource里获取数据库连接对象Connection;
- 在取得的数据库连接上创建事务对象Transaction;
- 创建Executor对象(该对象非常重要,事实上sqlsession的所有操作都是通过它完成的);
- 创建sqlsession对象。
Executor执行MappedStatement:
sqlSession是个门面,真正执行的是Executor,Executor通过动态代理的方式将任务扔给MapperProxy;
**StatementHandler:**最后sql的处理都是通过 StatementHandler,简单来说就是他包装了JDBC的操作;
四、Mybatis的主要特性
1.动态sql
主要是要区分SqlSource和BoundSql,前者是Mapper映射文件的对象,后者是解析好的sql对象,Mybatis会将动态sql解析成对应的BoundSql。
2.插件机制
Mybatis允许对映射文件配置好的sql语句进行拦截后进行处理,其实现方式是通过实现接口Interceptor来实现。
3.数据库连接池
Mybatis可以通过配置数据库连接池来对connection进行复用,可选择的连接池方案为:(1)UNPOOLED 不使用连接池的数据源;(2)POOLED 使用连接池的数据源;(3)JNDI 使用JNDI实现的数据源.
4.事务管理
Mybatis使用了JDBC的事务管理器,但如果集成了Spring,则可以不配置事务管理器,Spring的事务管理器会将其纳入事务管理。
5.缓存管理
Mybatis通过二级缓存来进行缓存管理,一级缓存是通过Mybatis自带的Map数据类型,来缓存执行过的SQL结果,每次执行Executor会在该Map中查询是否有相关执行的结果;二级缓存是可以配置第三方的缓存实现,比如redis或memcached等。
参考资料
- ♥Mybatis知识体系详解♥:https://www.pdai.tech/md/framework/orm-mybatis/mybatis-overview.html
- mybatis官方文档:https://mybatis.org/mybatis-3/zh/index.html