mybatis运行流程
2020-06-15 11:50:07 0 举报
AI智能生成
mybatis运行流程
作者其他创作
大纲/内容
mybatis流程具象化
SqlSessionFactoryBuilder
工厂建造工人
创建工厂
Configuration
小箱子
放置说明书,记录操作过程
sqlSessionFactory
管子生产工厂
生产管子
SqlSession
管子
控制水流,调用开关
Executor
智能开关
设置水流大小
StatementHandler
水流形状转化器(入口)
转化水流形状,宽窄,三角形,最窄的时候,相当于关闭,所以可以控制水流大小
ResultSetHandler
出口形状转换
黑心的水资源提供者,中间商减小水流,垄断,高价买水
全流程顺序
SqlSessionFactoryBuilder
Configuration
MappedStatement
SqlSource
resultmap
sqlSessionFactory
SqlSession
Executor
StatementHandler
ParameterHandler
TypeHandler
ResultSetHandler
mybatis流程具象化_测试
SqlSessionFactoryBuilder
查询缓存工厂建造者
Configuration
配置
sqlSessionFactory
查询缓存工厂
会话工厂
SqlSession
查询缓存
Executor
执行者
StatementHandler
声明处理程序
声明管理者
ResultSetHandler
结果集处理程序
水流管子工厂放水事件
管子水流工厂简版
小箱子
工厂建造工人
管子生产工厂
智能开关
水流形状转化器(入口)
管子
出口形状转换
黑心的水资源提供者,中间商减小水流,垄断,高价买水
简述: 工厂建造者建造了一个工厂,通过一个小册子,工厂将建立池子的说明书(后续可以持续更新)的放入小箱子,工厂建立了一个连接产品通道(管子)的池子, 池子创建了一个通道(sqlsession) ,池子使用了query,开关按钮(excutor)打开,水流就通过了(一段sql),可以修改删除水流.开关,有一个指针,可以设置放水流的大小.开关是智能开关,还有记录水流量的功能,为了防止开关出现问题,加快水流调度的速度,防止误触,最终还有一个保险按钮(如同手枪的保险)ResultSetHandler.
简介
MyBatis框架主要完成的是以下2件事情:
根据JDBC规范建立与数据库的连接。
通过反射打通Java对象与数据库参数交互之间相互转换的关系。
比喻
餐厅的服务流程
第一个是跟客户打交道的服务员,它是用来接收程序的工作指令的,我们把它叫做接口层。
第二个是后台的厨师,他们根据客户的点菜单,把原材料加工成成品,然后传到窗口。这一层是真正去操作数据的,我们把它叫做核心层。
最后就是餐厅也需要有人做后勤(比如清洁、采购、财务),来支持厨师的工作和整个餐厅的运营。我们把它叫做基础层。
动态代理
太监
接口Class对象是大内太监,里面的方法和字段比做他的一身武艺,但是他没有小DD(构造器),
所以不能new实例。一身武艺后继无人。
那怎么办呢?
正常途径(implements)
写一个类,实现该接口。这个就相当于大街上拉了一个人,认他做干爹。一身武艺传给他,只是比他干爹多了小DD,可以new实例。
非正常途径(动态代理):
通过妙手圣医Proxy的克隆大法(Proxy.getProxyClass())克隆一个Class,但是有小DD。所以这个克隆人Class可以创建实例,也就是代理对象。
代理Class其实就是附有构造器的接口Class,一样的类结构信息,却能创建实例。
特殊
比如MyBatis对动态SQL的解析
组合模式
简述
阶段
初始化阶段:读取XML配置文件和注解中的配置信息,创建解析对象,并完成各个模块的初始化工作。就是把我们的配置文件加载到内存里面去。在sqlSession初始化的时候加载到内存中去的。
代理阶段:封装iBatis的编程模型,使用mapper接口开发的初始化工作;
数据读写阶段:通过SqlSession完成SQL的解析,参数的映射,SQL的执行,结果的反射解析过程。
MyBatis的设计思路
创建SqlSessionFactory实例
实例化过程中,加载配置文件创建configuration对象
通过factory创建SqlSession
通过SqlSession获取mapper接口动态代理
动态代理回调sqlsession中某查询方法
SqlSession将查询方法转发给Executor
Executor基于JDBC访问数据库获取数据
Executor通过反射将数据转换成POJO并返回;给SqlSession
将数据返回给调用者
分层
接口层
首先接口层是我们打交道最多的。核心对象是SqlSession,它是上层应用和MyBatis打交道的桥梁,SqlSession 上定义了非常多的对数据库的操作方法。接口层在接收到调用请求的时候,会调用核心处理层的相应模块来完成具体的数据库操作。
两种方式
a.使用传统的MyBatis提供的API;
这是传统的传递Statement Id 和查询参数给 SqlSession 对象,使用 SqlSession对象完成和数据库的交互;MyBatis 提供了非常方便和简单的API,供用户实现对数据库的增删改查数据操作,以及对数据库连接信息和MyBatis 自身配置信息的维护操作
上述使用MyBatis 的方法,是创建一个和数据库打交道的SqlSession对象,然后根据Statement Id 和参数来操作数据库,这种方式固然很简单和实用,但是它不符合面向对象语言的概念和面向接口编程的编程习惯。由于面向接口的编程是面向对象的大趋势,MyBatis 为了适应这一趋势,增加了第二种使用MyBatis 支持接口(Interface)调用方式。
b. 使用Mapper接口
MyBatis 将配置文件中的每一个 节点抽象为一个 Mapper 接口,而这个接口中声明的方法和跟 节点中的 节点项对应,即 节点的id值为Mapper 接口中的方法名称,parameterType 值表示Mapper 对应方法的入参类型,而resultMap 值则对应了Mapper 接口表示的返回值类型或者返回结果集的元素类型。
据MyBatis 的配置规范配置好后,通过SqlSession.getMapper(XXXMapper.class) 方法,MyBatis 会根据相应的接口声明的方法信息,通过动态代理机制生成一个Mapper 实例,我们使用Mapper 接口的某一个方法时,MyBatis 会根据这个方法的方法名和参数类型,确定Statement Id,底层还是通过SqlSession.select("statementId",parameterObject);或者SqlSession.update("statementId",parameterObject); 等等来实现对数据库的操作,(至于这里的动态机制是怎样实现的,我将准备专门一片文章来讨论,敬请关注~)
MyBatis 引用Mapper 接口这种调用方式,纯粹是为了满足面向接口编程的需要。(其实还有一个原因是在于,面向接口的编程,使得用户在接口上可以使用注解来配置SQL语句,这样就可以脱离XML配置文件,实现“0配置”
核心处理层
内容
接下来是核心处理层。既然叫核心处理层,也就是跟数据库操作相关的动作都是在这一层完成的。核心处理层主要做了这几件事
插件也属于核心层,这是由它的工作方式和拦截的对象决定的。
主要功能
a. 通过传入参数构建动态SQL语句;
b. SQL语句的执行以及封装查询结果集成List
步骤
把接口中传入的参数解析并且映射成JDBC 类型;
解析xml 文件中的SQL 语句,包括插入参数,和动态SQL 的生成;
执行SQL 语句;
处理结果集,并映射成Java 对象。
基础支持层
内容
最后一个就是基础支持层。基础支持层主要是一些抽取出来的通用的功能(实现复用),用来支持核心处理层的功能。比如数据源、缓存(请点击跳转至缓存详解)、日志、xml 解析、反射、IO、事务等等这些功能。
3大机制和sql配置
3.1. 事务管理机制
3.2. 连接池管理机制
3.3. 缓存机制
3. 4. SQL语句的配置方式
传统的MyBatis 配置SQL 语句方式就是使用XML文件进行配置的,但是这种方式不能很好地支持面向接口编程的理念,为了支持面向接口的编程,MyBatis 引入了Mapper接口的概念,面向接口的引入,对使用注解来配置SQL 语句成为可能,用户只需要在接口上添加必要的注解即可,不用再去配置XML文件了,但是,目前的MyBatis 只是对注解配置SQL 语句提供了有限的支持,某些高级功能还是要依赖XML配置文件配置SQL 语句。
步骤
通过建造者模式创建一个工厂类,定位,加载,解析配置文件的就是在这一步完成的,包括mybatis-config.xml 和Mapper 适配器文件。
通过SqlSessionFactory 创建一个SqlSession。
获得Mapper 对象。
调用接口方法(insert,delete,update,select)。
主要部件
SqlSessionFactoryBuilder
通过SqlSessionFactoryBuilder 解析mybatis-config.xml 文件中的 Configuration 创建一个 sqlSessionFactory
Configuration
MyBatis所有的配置信息都维持在Configuration对象之中。
sqlSessionFactory
通过sqlSessionFactory 创建一个SqlSession
SqlSession
SqlSession 调用一个 quary(查询)Executor执行器,是为了执行sql语句
作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能
SqlSession根据Statement ID, 在mybatis配置对象Configuration中获取到对应的MappedStatement对象,然后调用mybatis执行器来执行具体的操作。
Executor
创建一个新的StatementHandler (参数执行器)
MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护
功能
(1、根据传递的参数,完成SQL语句的动态解析,生成BoundSql对象,供StatementHandler使用;
(2、为查询创建缓存,以提高性能(具体它的缓存机制不是本文的重点,我会单独拿出来跟大家探讨,感兴趣的读者可以关注我的其他博文);
(3、创建JDBC的Statement连接对象,传递给StatementHandler对象,返回List查询结果。
StatementHandler
调用ResultSetHandler (结果器返回结果),执行SQl语句,不同的SQl语句返回不同的结果
封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合
ResultSetHandler
负责将JDBC返回的ResultSet结果集对象转换成List类型的集合
其他部件
ParameterHandler
负责对用户传递的参数转换成JDBC Statement 所需要的参数,
TypeHandler
负责java数据类型和jdbc数据类型之间的映射和转换
jdbc
statement
preparedstatement
simplestatement
callablestatement
resultset
MappedStatement
MappedStatement维护了一条
包含
SqlSource
负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
resultmap
BoundSql
表示动态生成的SQL语句以及相应的参数信息
MapperProxy
MapperProxyFactory
代理对象,用于代理Mapper接口方法
详细步骤流程
第一步配置解析过程:
定位资源位置,加载资源,将xml加载成流
组件
SqlSessionFactoryBuilder
功能
build 加载配置文件
new XMLConfigBuilder 配置文件解析器
build(config) 建立解析完的 Configuration
调用new DefaultSqlSessionFactory
XMLConfigBuilder
XMLMapperBuilder
XMLStatementBuilder
作用
是抽象类BaseBuilder 的一个子类,专门用来解析全局配置文件,针对不同的构建目标还有其他的一些子类
解析-config 配置文件、Mapper 文件、Mapper 接口上的注解的解析
功能
调用 new Configuration
Parse()解析全集配置文件及映射器文件,填充Configuration 及MpppedStatement
方法
parse()
是对Mapper 映射器的解析
Configuration
注意
MyBatis 全局配置文件的顺序不可以颠倒
最后,MapperRegistry 也会放到Configuration 里面去。
把 Configuration 返回给 XMLConfigBuilder
DefaultSqlSessionFactory
返回给SqlSessionFactoryBuilder一个 DefaultSqlSessionFactory
第二步会话创建过程:
DefaultSqlSessionFactory
取到opensqlsession
getDefaultExecutorType()
获取执行器类型
openSessionFromDataSource
new DefaultSqlSessioh(this.configuratilon, edecutor, autoCommit);
Configuration
返回执行器类型
获取 Enviroment
创建事务TX
创建执行器类 newExecutor(tx, execType)
Executor
1.创建Executor基本类型
SINPLE/REUSE/BATCH
2.二级缓存包装
CachingExecutor((Executot)executor)
3.拦截器包装
DefaultSqlSession
第三步获得Mapper 对象:
组件
DefaultSqlSession
getMapper(Claaa type)
Configuration
getMapper(Claaa type)
MapperRegistry
根据接口类型获取工厂类(MapperProxyFactory this
.knownMappers.get(type)
MapperProxyFactory
newInstance()创建MapperProxy实例
Proxy.newProxyInstance
创建接口代理对象
MapperProxy
返回MapperProxy实例
疑问
Mapper 对象是怎么获得的?
DefaultSqlSession 的getMapper()方法,调用了Configuration 的getMapper()方法。继而调到 MapperRegistry.getMapper:
JDK 动态代理和MyBatis 用到的JDK 动态代理有什么区别
不需要实现类的原因:我们只需要根据接口类型+方法的名称,就可以找到Statement ID 了,而唯一要做的一件事情也是这件,所以不需要实现类.在MapperProxy里面直接执行逻辑(也就是执行SQL)就可以
注意
获得Mapper 对象的过程,实质上是获取了一个MapperProxy 的代理对象
第四步执行sql:
MapperProxy
invoke()
MapperMethod
执行execute(this.sqlSession,args)
DefaultSqlSession
1.selectone
2.selectList
3.获取MappedStlatement执行query()
BaseExecutor
1.获取BoundSq1
2.创建CacheKey
3.获取本地缓存queryFromDatabase插入本地缓存
simpleExecutor
1.获取Configuration
2.创建StatementHandler\parameterHandler\ResultSetHandler
3.创建Connection
4.parameterize处理参数Handler.query(stmt,resultHandler)
RoutingstatementHandler
1.语句编译
2.ps.execute()执行sqlhandleResultSets
DefaultResultSetHandler
处理结果集
0 条评论
下一页