目录
SqlSessionFactory 有两个实现类:
一个是 SqlSessionManager 类,
一个是 DefaultSqlSessionFactory 类
- DefaultSqlSessionFactory : SqlSessionFactory 的默认实现类,是真正生产会话的工厂类,这个类的实例的生命周期是全局的,它只会在首次调用时生成一个实例(单例模式),就一直存在直到服务器关闭。
- SqlSessionManager :已被废弃,原因大概是: SqlSessionManager 中需要维护一个自己的线程池,而使用MyBatis 更多的是要与 Spring 进行集成,并不会单独使用,所以维护自己的 ThreadLocal 并没有什么意义,所以 SqlSessionManager 已经不再使用。
- //使用建造者模式的设计思想
- SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSessionFactory创建流程:
- 通过mybatis的Resources来读取全局配置文件,然后以流的形式作为SqlSessionFactoryBuilder的build方法的参数传入;
- SqlSessionFactoryBuilder根据参数创建XMLConfigBuilder对象,然后调用parse方法生成Configuration对象;
- 然后SqlSessionFactoryBuilder根据Configuration对象作为参数,调用重载方法build,生成DefaultSqlSessionFactory对象并返回
注:
解析mapper.xml时,Mybatis会把每个SQL标签封装成
SqlSource
对象,然后根据SQL语句的不同,又分为动态SQL和静态SQL。其中,静态SQL包含一段String类型的sql语句;而动态SQL则是由一个个SqlNode
组成。Mybatis会为每个SQL标签生成MappedStatement对象,保存在Configuration对象中。
MappedStatement的结构:
id:全限定类名+方法名组成的ID
sqlSource:当前SQL标签对应的
SqlSource
对象
SqlSession sqlSession = sqlSessionFactory.openSession();
通过 SqlSessionFactory 对象得到 SqlSession,然后就可以执行 SQL 语句了。该过程中主要创建了两个与我们分析执行流程重要的对象,一个是 Executor 执行器对象,一个是 SqlSession 对象。
SqlSession 中定义了一系列模版方法,让你能够执行简单的 CRUD 操作,也能获取映射、管理事务,例如涉及事务的 commit、 rollback、close 等方法。这是模版设计模式的一种应用。(SqlSession 本身不做任何业务处理操作,交给Excutor执行)
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
MapperProxy 是 Mapper 映射 SQL 语句的关键对象,我们写的 Mapper 层都是通过 MapperProxy 来和对应的 SQL 语句进行绑定的。
调用过程:
SqlSession -> Configuration -> MapperRegistry -> MapperProxyFactory,最终执行了
Proxy.newProxyInstance(),最终生成了MapperProxy 。
当我们调用mapper接口方法的时候,实际调用到代理对象的invoke()
方法,最后其实是调用了Executor中的逻辑。
每一个 SqlSession 都会拥有一个 Executor 对象。Executor 的核心作用是处理SQL请求、事务管理、维护缓存以及批处理等 。执行器在的角色更像是一个管理员,接收SQL请求,然后根据缓存、批处理等逻辑来决定如何执行这个SQL请求。并交给JDBC处理器执行具体SQL。
Executor有主要的三个实现子类。分别是:SimpleExecutor(简单执行器)、ReuseExecutor(重用执行器)、BatchExecutor(批处理执行器)。
简单执行器
SimpleExecutor是默认执行器,它的行为是每处理一次会话当中的SQl请求都会通过对应的StatementHandler 构建一个新的Statement,这就会导致即使是相同SQL语句也无法重用Statement,所以就有了(ReuseExecutor)可重用执行器可重用执行器
ReuseExecutor 区别在于他会将在会话期间内的Statement进行缓存,并使用SQL语句作为Key。所以当执行下一请求的时候,不再重复构建Statement,而是从缓存中取出并设置参数,然后执行。批处理执行器
BatchExecutor 顾名思议,它就是用来作批处理的。但会将所有SQL请求集中起来,最后调用Executor.flushStatements() 方法时一次性将所有请求发送至数据库。
Executor还有BaseExecutor(基础执行器)和CachingExecutor(缓存执行器)。
基础执行器
主要是用于维护缓存和事务。它实现了Executor中的query与update方法。处理SQL请求时先根据SQL及参数判断缓存中是否存在数据,有就走缓存。否则就会交给下面的子类处理。BaseExecutor 只有一级缓存
缓存执行器
其实是二级缓存。二级缓存可以通过参数控制关闭,而一级缓存不可以。二级缓存采用了装饰者设计模式,处理完二级缓存逻辑之后,把SQL执行相关的逻辑交给实际的Executor处理(交由BaseExecutor 以及其子类处理)
在实际的一次调用中,Excutor会调用到MapperMethod的execute()
方法并进入查询的逻辑分支。
MapperMethod关联着本次执行方法所对应的
SQL
语句以及入参和出参等信息,当mapper方法被调用的时候对应的MapperProxy会生成相应的MapperMethod并且会缓存起来
MapperMethod
的两大属性:
SqlCommand -
MappedStatement信息和类型信息(SELECT,UPDATE...)
MethodSignature -
方法的参数信息和返回值信息
在上述的MapperMethod的execute()
方法中,会根据这两个属性进入不同的分支,(首先查缓存)在具体分支的方法中通过根据属性信息( “全限定类名+方法名
” )拿到MappedStatement对象,然后通过Executor 交给StatementHandler 去执行里面封装的Sql语句。
StatementHandler 负责基于实例化并操作 Statement 对象与数据库进行交互,在工作时还会使用 ParameterHandler 和 ResultSetHandler对参数进行映射,对结果进行实体类的绑定。
ParameterHandler 负责为 PreparedStatement 的 sql 语句参数动态赋值
ResultSetHandler 负责处理 Statement 执行后产生的结果集,生成结果列表,并处理存储过程执行后的输出参数,返回给客户端
SimpleStatementHandler: 管理 Statement 对象并向数据库中推送不需要预编译的SQL语句。
PreparedStatementHandler: 管理 Statement 对象并向数据中推送需要预编译的SQL语句。
CallableStatementHandler:管理 Statement 对象并调用数据库中的存储过程。