mybatis运行流程
2020-06-15 11:50:07 0 举报
AI智能生成
登录查看完整内容
mybatis运行流程
作者其他创作
大纲/内容
mybatis流程具象化
SqlSessionFactoryBuilder
工厂建造工人
创建工厂
Configuration
小箱子
sqlSessionFactory
管子生产工厂
生产管子
SqlSession
管子
Executor
智能开关
设置水流大小
StatementHandler
水流形状转化器(入口)
ResultSetHandler
出口形状转换
全流程顺序
MappedStatement
SqlSource
resultmap
ParameterHandler
TypeHandler
mybatis流程具象化_测试
查询缓存工厂建造者
配置
查询缓存工厂
会话工厂
查询缓存
执行者
声明处理程序
声明管理者
结果集处理程序
水流管子工厂放水事件
管子水流工厂简版
mybatis运行流程
简介
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\
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 对象。
主要部件
通过SqlSessionFactoryBuilder 解析mybatis-config.xml 文件中的 Configuration 创建一个 sqlSessionFactory
MyBatis所有的配置信息都维持在Configuration对象之中。
通过sqlSessionFactory 创建一个SqlSession
SqlSession 调用一个 quary(查询)Executor执行器,是为了执行sql语句
作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能
创建一个新的StatementHandler (参数执行器)
MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护
功能
(1、根据传递的参数,完成SQL语句的动态解析,生成BoundSql对象,供StatementHandler使用;
(2、为查询创建缓存,以提高性能(具体它的缓存机制不是本文的重点,我会单独拿出来跟大家探讨,感兴趣的读者可以关注我的其他博文);
(3、创建JDBC的Statement连接对象,传递给StatementHandler对象,返回List查询结果。
封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合
负责将JDBC返回的ResultSet结果集对象转换成List类型的集合
其他部件
负责对用户传递的参数转换成JDBC Statement 所需要的参数,
负责java数据类型和jdbc数据类型之间的映射和转换
jdbc
statement
preparedstatement
simplestatement
callablestatement
resultset
MappedStatement维护了一条节点的封装,
包含
负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
BoundSql
表示动态生成的SQL语句以及相应的参数信息
MapperProxy
MapperProxyFactory
代理对象,用于代理Mapper接口方法
详细步骤流程
第一步配置解析过程:
定位资源位置,加载资源,将xml加载成流
组件
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
第二步会话创建过程:
取到opensqlsession
getDefaultExecutorType()获取执行器类型
openSessionFromDataSource
返回执行器类型
获取 Enviroment
创建事务TX
1.创建Executor基本类型
SINPLE/REUSE/BATCH
2.二级缓存包装
CachingExecutor((Executot)executor)
3.拦截器包装
DefaultSqlSession
第三步获得Mapper 对象:
getMapper(Claaa type)
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:
invoke()
MapperMethod
执行execute(this.sqlSession,args)
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 条评论
回复 删除
下一页