多年以前猿小二刚刚进入程序猿的大军中,每天都在快乐的coding,那个时候经常要更数据打交道,所以编写很多JDBC的代码,动不动就得写JDBC六部曲。
注册驱动
获取Connection连接
执行预编译
执行SQL
封装结果集
释放资源
越写越熟练,甚至有种自己写代码的功力有点超神的错觉;经过了一段时间的重复,猿小二意识到自己每天都在写重复的代码。而且,每次如果要更改sql语句或者配置信息的时候,都要跑到JDBC程序当中去修改,这可是很麻烦的事儿,不仅造成了硬编码的问题,还特别的影响开发效率。
要把大象装冰箱总共分几步?
一天,猿小二突然意识到,程序猿不是要来改变的世界的吗?我就是程序猿啊,我应该去改变世界啊,现在不就有一个机会吗?如果程序猿每天都在写这种繁琐且没有技术含量的代码,哪里有时间去改变世界,所以猿小二立下flag,要为程序猿提供一个更加方便的技术来操作数据库。
一开始猿小二也是毫无头绪,但是猿小二拉来一个自己神一般存在的大牛同学狮小三;他们一起讨论如何才能简化JDBC开发的过程,让程序猿不在关注注册驱动、获取链接、编译sql、封装结果集、以及释放资源这些重复的代码。
于是他们开始了对JDBC执行过程的分析,并最终将这六步曲分成了三个模块。
接口层 :对外暴露的API
核心处理层:提供配置文上件的解析、sql语句的解析、结果集的封装等
基础支撑层:提供基础的环境支撑,如数据源的配置、事物的管理等
最终他们经过很长时间的讨论和优化,给出了一个比较满意的设计,这就是MyBatis框架的基础设计原型。
我们都知道Mybatis是一个非常小巧灵活的ORM框架,深受国内广大开发者的喜爱,它的出现某种程度了是为了消除所有的JDBC代码和参数的手工设置以及结果集的封装问题。
这篇文章我们就来了解MyBatis是怎样对JDBC进行封装和架构思考的,进而掌握MyBatis的核心架构设计。
并对这三部分的具体的职责,进行了分析和解释。
接口层
提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。程序猿不用管具体的内部实现,只需要根据自己的需求调用相应的api就可以了,并且还提供了两种使用的方式。
传统的方式
就是在一个SqlSession的接口中定义很多方法,程序猿可以根据自己的需要调用具体的增删改查方法。
Mapper代理的方式
Mapper代理的方式实际上是通过创建mapper接口的代理对象去调用接口中的方法,但底层其实还是调用的传统的API方法。
核心处理层
这部分主要就JDBC的核心内容了,包括参数映射、类型转换、SQL解析、SQL执行以及结果的封装,这部分内容就可以理解成JDBC的核心内容,这里它们抽出封装了四个核心的类,分别负责不同的功能。
ParameterHandler:SQL的参数处理,如:占位符等
ResultSetHandler:结果集处理
StatementHandler:封装了JDBC Statement操作,设置参数
Executor:执行器,真正用于执行增删改查操作
基础支撑层
这部分主要是抽取出来的通用组件包括数据源管理、事务管理、配置加载和缓存处理;为上层的数据处理层提供最基础的支撑。
数据源管理
数据源的管理对于持久层的框架来说,可谓是非常的重要,稍有不慎就会浪费大量系统资源,MyBatis也对此做了很好的支持,MyBatis有三种内建的数据源类型UNPOOLED、POOLED、JNDI。
UNPOOLED: 这个数据源的实现会每次请求时打开和关闭连接
POOLED: 这种数据源的实现利用“池”的概念将 JDBC连接对象组织起来,避免了创建新的连接实例时所必需的初始化和认证时间
JNDI : 这个数据源实现是为了能在如EJB 或应用服务器这类容器中使用,容器可以集中或在外部配置数据源,然后放置一个 JNDI上下文的数据源引用。这种已经不用了
通常情况下,我们是会使用POOLED的,可以帮他我们节省很多宝贵的系统资源。
事务管理
在MyBatis中有两种类型的事务管理器(JDBC/ MANAGED)它通过一个顶层的Transaction接口以及其不同实现JdbcTransaction和 ManagedTransaction来实现对事务的管理:
JDBC :这个配置直接使用了 JDBC 的提交和回滚设施,它依赖从数据源获得的连接来管理事务作用域,对应的实现类JdbcTransaction
MANAGED : 这个配置几乎没做什么。它从不提交或回滚一个连接,而是让容器来管理事务的整个生命周期(比如 JEE 应用服务器的上下文),对应的实现类ManagedTransaction
对事务的管理,在和Spring整合之后,通常会用Spring的事务管理器。
缓存处理
缓存对于持久层框架来说还是非常重要的,一定程度上可以减少和数据库的交互,MyBatis的提供了两种缓存机制,一级缓存和二级缓存。
一级缓存:是SqlSession级别的缓存,也就是会话级别的,如果两个相同的查询,第二次的查询会直接先从缓存中去拿,以及缓存也是默认开启的,这部分我们在源码分析的内容里会详细分析
二级缓存:是Mapper级别的缓存,也就是一个xxx.xml内的查询是可以共用的,需要手动开启
每一项新技术的诞生,背后都有一段不为人知的故事,就这样MyBatis框架的原型诞生了,通过这篇文章我们可以从整体上对MyBatis框架有个清晰的认识。