第一章mybatis第二讲-分析mybatis和手写mybatis (前47分钟学习笔记)
前言
2020.12.22 是正式开始学本课的日子,这一课分析框架,并且要求尝试手写框架。对我这个水平的学习者而言,课上的知识可能是用不到的,但是能记录的我还是会进行记录。
本文和本文内一切内容,均来自我对于开课吧Java企业级分布式架构师010期课程的学习笔记,并在我自身的理解上整理而成.
本课为长课程,因此学习方式建议遵循3+模型,第一遍概况,最后一遍审核,中间回放n次详细了解知识点。
2020.12.24 全课长2个半小时,前47分钟为框架分析。
跳过手写框架部分,暂时认为没有必要,掌握大量的技术不代表自身阶位够高,以实用为主,后续技术的广度和深度应等到基础技术熟练且无法突破时再进行
(课件中包含讲义,可以进行参考,但是应确保自身掌握具体内容)
第一章mybatis第二讲-分析mybatis和手写mybatis (前47分钟)
课程主题
手写mybatis框架分析&分析mybatis框架原理
(本次我只学分析,不学手写)
课程目标
- 先去分析原生JDBC存在的问题
- 掌握mybatis的框架原理
- 了解SqlSource、SqlNode的作用 (暂无)
- 掌握手写框架的面向对象思想(最终需要体会面向对象思想、设计模式)(暂无)
目标1:分析原生JDBC存在的问题
(关于jdbc,在我的记忆中是直接用java语句进行数据库操作,这种操作模式肯定是不行的)
(对于jdbc代码的演示进行略过,没有必要)
jdbc操作有个标准的8步骤模式:
- 第一步,加载数据库驱动
- 第二步,通过驱动管理类获取数据库链接(connection = DriverManager)
- 第三步,定义sql语句?表示占位符
- 第四步,获取预处理statement(声明)
- 第五步,设置为操作语句设置参数
- 第六步,向数据库发出sql语句执行动作
- 第七步,处理查询结果
- 第八步,释放资源
而在Mybatis架构中,一和二合并,三四五六合并,
通常为4步,实现了简化,尤其简化了数据库加载和业务sql语句部分。通过sqlsession和相关其他配置的的方式。
这种简化的方式是遵循了设计模式中的开闭原则
开闭原则
区分变量和不变量,尽量实现不将变量写死,使得变量环境调用不变量环境的框架(重复使用的功能尽量设计的可以被多种环境复用)
比如在加载数据库驱动的工程中用.propertiy文件来配置连接数据的参数,而不是在代码中写死。
此外在JDBC第三步中,直接以string字符串合成sql语句,采用硬编码的方式,也是不提倡的。
综上问题有如下3个:
创建连接、执行statement存在硬编码问题,并且太过臃肿。
创建连接存在硬编码问题(解决方案)
使用使用配置文件来解决硬编码的问题
连接数据库部分的硬编码问题,在Mybatis架构中通过全局配置文件得以解决,并且只使用一个文件(全局配置文件),在全局使用过程中只需要创建一次(创建多次也是可以的,但是大部分情况下,只需要创建一次)。
执行statement存在硬编码(sql语句、参数信息、返回值信息)(解决方案)
使用配置文件来解决硬编码的问题
也是使用配置文件来解决,在Mybatis架构中,存放sql语句的mapper文件和接口类(以XXXMapper.xml的方式)就是这类问题的解决方案。
并且为了方便管理,可以创建N个映射文件,不同的业务模块采用不同的配置文件。
代码太臃肿
JDBC的代码步骤太多,虽然Mybatis的代码也可以写成多步骤的模式,但是由于个个模块的复用性良好,并且可以进行全局管理,因此Mybatis架构在具体业务执行时只需要一行调用接口的代码。
解决方案
通过接口的设计模式,让程序员只需要调用接口函数,或者类似的方式就能实现CRUD功能(数据库操作)
(举例:略,从自己的项目中看,有很多)
课程进度
到这一步,课时为17分钟。
目标1.5:手写框架的思路分析
在开始Mybatis框架分析前,先思考一下如何手写框架。
所谓框架,就意味着将结构作为骨架,将复用性高的作为墙面,将业务功能作为门窗,因此,首先需要准备配置文件,配置文件就是建墙的砖。
配置文件的编写
配置文件一方面符合了复用性原则,另一方面符合了开闭原则,因此设计配置文件是必须的。
全局配置文件
那些全局调用的参数组应当拥有自身的全局配置文件,并且全局配置文件也可以拥有自己的标签参数文件进行进一轮的开闭原则设计。
映射文件
我写的很熟的文件,将复杂的sql语句封装在此,运用静态方式和动态方式进行简化。映射文件的主要作用依然是模块化的切割功能,使得便于维护,否则可以直接使用注解方式(详见入门教程)进行编写。
加载配置文件
加载配置文件通过加载全局配置文件的方式进行,其他配置文件通过全局配置文件来加载,形成套娃结构,使得最上层接触最少但是最有效的信息
因此分为5步:
- 指定全局配置文件的路径
- 获取InputStream
- 创建Document对象
- 按照mybatis的标签语义(比如select)去解析Document对象(这里面还包含映射文件的解析,但是那是另一个流程)
- 使用一个对象将整个配置文件的信息进行封装Configuration对象
关于映射文件的解析:
映射文件最终也会通过对象去封装解析后的信息(多个MappedStatement对象)
在上述的流程中最为复杂的是对象解析,主要会生成如下(课上没详细讲,略过)
SqlSource
SqlNode
BoundSql
准备接口文件
对外接口一定要简洁,符合函数的模型,输入所需内容,输出所需内容,这个很简单。
而困难的地方在于,这个接口的底层依旧是需要用JDBC代码来处理,
需要处理的内容主要是:
- 获取连接(在全局配置文件中,配置数据源),此处就可以通过配置的数据源连接池获取连接
- 获取sql语句(编写在映射文件中的)(需要进行解析)
- 创建Statement对象
- 设置参数(参数值是通过接口传入的。入参信息,都是通过解析sql语句获取到的)
- 执行statement
- 处理结果集(要映射的结果类型是在映射文件文件中配置的)
课程进度
到这一步,课时为30分钟。
目标2:掌握mybatis的框架原理
原理部分信息密度过高,因此需要搭配图片学习,图片来自于学习课件。
(另外发现这部分知识有部分课件没有详细讲,因为详细原理可以在应用中学习,现在记录了后续没有运用也会忘记,而运用的时候自然可以学会。)
架构图
在Mybatis架构中,通常采用上图的的3重结构,最上层的接口层为我们程序员编写时使用,而数据处理层常在编写映射文件时有所交互,根据其中的规则进行设计代码,最底层的基础支撑层,仅在全局操作时有所触碰。这3重结构使得程序员对于代码编写的简易度和舒适度大幅度提升。
这3重结构跟工程的3重结构类似,工程三重结构为表现层,业务层,持久层。从中可以看出这种分层的依据,首先是底层的持久层或者是支撑层是根基,其次是执行功能的业务层或者是处理层完成承上启下的作用,最后是关键的表现层或者是接口层,这部分对外公开,可见架构的目的之一就是为了简化对外的表现形式。
接口层
略,是Mybatis架构提供给开发着调用api的接口
数据处理层
在整体架构中起着承上启下的作用,作为sql操作的主体,这部分尤为重要。
但是这部分同样并不复杂,核心依旧是输入输出和执行,其复杂的部分在于:
- 将输入参数进行映射
- 将sql语句进行解析
- 运行sql语句并生成结果
基础支撑层
负责Mybatis架构与数据库的基本连接方式以及SQL命令和配置文件的映射关系。
负责:管理连接,管理事务,加载文件,管理缓存
架构流程图
图上的注解来自课程的讲师我不做复述,我记录我的见解。
从构图上看,可以分为纵向构图和横向构图
纵向构图
纵向构图中可以划分为3个阶段,
- 第一个阶段:加载配置文件并生成结果
在这个阶段的离开时,生成了下一阶段需要的sqlSessionFactory ,在之前的课中讲到:sqlSessionFactory作为会话工厂,可以单例管理,只创建一次然后重复使用。这是生成会话sqlSession所需的全部条件总和。在这个过程中根据配置文件会生成后续需要使用的configuration对象,而这个对象将被会话工厂使用 - 第二个阶段:生成statement
在这个阶段离开时,已经准备好了操作数据的具体动作,在这个阶段中生成对外调用的接口,而接口被调用时使用阶段1内生成的configuration对象。
而这个阶段需要创建的会话会很多,创建这个会话的动作由上一阶段的会话工厂来创建 - 第三阶段:数据库操作
这部分略过。
横向构图
从输入输出角度看,Mybatis架构实现了将连接配置的部分和底层操作数据库的部分隐藏,因此用户只需要将操作动作需要的参数输入然后等待结果即可,而其他复杂的动作,包括连接数据库,管理缓存,都不在用户的视野中。
总结
如果将原始的JDBC代码比作一条平铺在在地上的绳子,那么Mybatis架构就是将绳子连接底层的上端和具体操作的下端隐藏封装,仅拎起用户操作最关键的那一段。
调用流程图
这部分图对应架构流程图,则是纵向图解的第二阶段,或者是第一段结尾,详细的描述了,接口会话是如何向下运行执行任务的。图上的知识点不做复述,根据课程记录一些关键的类。
Mybatis四大组件(拦截器应用区域)
- Executor 执行工具,负责sql语句的生成,也负责管理缓存
- StatementHandler 负责jdbc和statement的交互,包括为statement/ 设置参数,和将JDBC返回的结果集变为list
- ParameterHandler 转换入参
- ResultSetHandler 转换出参
以上的主要作用是灵活的执行JDBC代码,而拦截器(自定义插件比如分页插件)就在这些范围内使用(分页插件拦截Executor)
其他图上的类
- sqlSession:架构顶层api接口,
- TypeHandler:类型转换,略
- Configuration:配置文件解析相关,之后课程讲解
- MappedStatement:配置文件解析相关,之后课程讲解
- SqlSource:sql语句封装相关,之后的课程讲解
- BoundSql:sql语句封装相关,之后的课程讲解
流程描述
向下:从sqlSession到Executor再到StatementHandler是第一重通路,
到Executor此处如果有配置二级缓存则在适当条件下(满足查询条件)不向下进行而是就此返回数据。
从StatementHandler向下是第二重通路
这部分内容跟jdbc部分有直接映射,这个通路的设计模型参照设计模式的相关思想。
(这部分课程讲的很模糊,我理解但是难以描述,知识点图上都有)
mapper代理执行原理
这部分课上没讲
直接上图
这个图目前无法理解,也不知道其设计的巧妙之处,所以不做说明。
结语
学了一天多的时间才完成课时的47的分钟内容,尽量的能理解的都理解,不赶进度。
剩下的技术内容暂时超出了我的能力范围因此到下一阶段再学习。
在本课中,我已经理解了Mybatis基础的框架构成,运行原理,结合之前的初级应用如果要我开发对应级别的项目我可以入手了,至此我停下进度。