本文来自http://www.bubuko.com/infodetail-549184.html

如果不太熟悉MyBatis使用的请先参见MyBatis官方文档,这对理解其架构设计和源码分析有很大好处。

一、概述

MyBatis并不是一个完整的ORM框架,其官方首页是这么介绍自己

The MyBatis data mapper framework makes it easier to use a relational database with object-oriented applications. MyBatis couples objects with stored procedures or SQL statements using a XML descriptor or annotations. Simplicity is the biggest advantage of the MyBatis data mapper over object relational mapping tools.
 

而在其官方文档中介绍“What is MyBaits”中说到

MyBatis is a first class persistence framework with support for custom SQL, stored procedures and advanced mappings. MyBatis eliminates almost all of the JDBC code and manual setting of parameters and retrieval of results. MyBatis can use simple XML or Annotations for configuration and map primitives, Map interfaces and Java POJOs (Plain Old Java Objects) to database records. 
 
ORM是Object和Relation之间的映射,包括Object->Relation和Relation->Object两方面。Hibernate是个完整的ORM框架,而MyBatis完成的是Relation->Object,也就是其所说的data mapper framework。关于ORM的一些设计思路和细节可以参见Martin Flow《企业应用架构模式》一书中的ORM章节,MyBatis并不刻意于完成ORM(对象映射)的完整概念,而是旨在更简单、更方便地完成数据库操作功能,减轻开发人员的工作量,我想这对于应用系统来说也是最实用的,相信用Hibernate的都受过它的痛苦,而用过MyBatis的都会感觉它很简捷轻松。

二、整体架构

下面是从功能流程层次描述MyBatis的整体架构图

而下面是MyBatis源码包对应的架构图

下面以“功能流程角度的架构图”来简要地分析下各层的架构,在后面系列文章中将有专题来深入解析MyBatis重要的功能点。

1、接口层

我们知道,在不考虑与Spring集成的情况下,使用MyBatis执行数据库操作的代码如下
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession session = sqlSessionFactory.openSession();
try {
  Blog blog = session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);
} finally {
  session.close();
}

SqlSessionFactory、SqlSession这是MyBatis接口层的核心类,尤其是SqlSession,是实现所有数据库操作的API,这几个类都是org.apache.ibatis.session包下的,这个包的主体类结构图如下

Configuration是MyBatis中相当重要的一个类,可以这么说,如果理解了其中的所有参数的意义,不仅清楚地知道MyBatis提供的所有配置项,还理解了MyBatis的内部核心运行原理,当然要真正理解这些参数的意义及实现,还需要阅读完完整的MyBatis框架之后才能做到。

由上图可以看到,Configuration对象与DefaultSqlSessionFactory是1:1的关联关系,这也就意味着在一个DefaultSqlSessionFactory衍生出来的所有SqlSession作用域里,Configuration对象是全局唯一的。同时SqlSessionFactory提供了getConfiguration()接口来公开Configuration对象,因此开发者除了配置文件之外,还可以在程序里动态更改Configuration的属性项以达到动态调整的目的,但此时不仅要考虑到执行完reset,同时还要考虑在修改过程中会可能影响到其他SqlSession的执行。

2、核心层

2.1 配置解析

在应用启动的时候,MyBatis解析两种配置文件

  • SqlMapConfig.xml
  • SqlMap.xml

SqlMapConfig.xml是在XMLConfigBuilder类中完成解析的,其类图关系大致如下

我们知道XML有两种解析方式:一是DOM,另一个是SAX,MyBatis使用的是org.wrc.dom——JDK提供的文档对象模型(DOM)接口(SqlMapConfig.xml并不大,所以DOM方式并没有什么效率损耗,JDK也提供了SAX模型接口org.xml.sax,这两个都是JAXP的组件API),以及JDK官方提供的javax.xml.xpath.XPath来作为XML路径寻找组件。

SqlMap.xml是在XMLMapperBuilder中解析完成的,其中把对Statement的解析(即SqlMap.xml中SELECT|INSERT|UPDATE|DELETE定义部分)委托给XMLStatementBuilder来完成。SqlMap.xml的解析比较复杂的,涉及到PreparedMapping、ResultMapping、LanguageDriver、Discriminator、缓存、自动映射等一系列对象的构造,这里暂时略过,后面专题分析。

2.2 SQL执行

MyBatis中Executor是的核心,围绕着它完成了数据库操作的完整过程。下面是Executor的类图

在上图中我列出了Executor中方法的参数,而在其子类中就没有明确写出。从上图中可以看到,Executor主要提供了

  • QUERY|UPDATE(INSERT和DELETE也是使用UPDATE),从方法定义中可看到,它需要MappedStatement、parameter、resultHandler这几个实例对象,这几个也是SQL执行的主要部分,详细实现在后面专题中再介绍。
  • 事务提交/回滚,这委托给Transaction对象来完成。
  • 缓存,createCacheKey()/isCached()。
  • 延迟加载,deferload()。
  • 关闭,close(),主要是事务回滚/关闭。

BaseExecutor的属性表明:它内部维护了localCache来localOutputParameterCache来处理缓存,至于这缓存保存的是什么,这后面专题再说。以及线程安全的延迟加载列表deferredLoads、事务对象Transaction。

BatchExecutor的属性已经表明:它内部维护了StatementList批量提交并通过batchResultList保存执行结果。

ResueExecutor的属性及方法表明:它内部维护了java.sql.Statement对象缓存,以重用Statement对象(对于支持预编译的数据库而言,在创建PreparedStatement时需要发送一次数据库请求预编译,而重用Statement对象主要是减少了这次预编译的网路开销)。

下面以SqlSession.selectList为例,画出SQL执行的时序图(点击下方的图片查看大图,部分分支有所简化)

3、基础层

3.1、logging:

MyBatis使用了自己定义的一套logging接口,根据开发者常使用的日志框架——Log4j、Log4j2、Apache Commons Log、java.util.logging、slf4j、stdout(控制台)——分别提供了适配器。由于各日志框架的Log级别分类法有所不同(比如java.util.logging.Level提供的是All、FINEST、FINER、FINE、CONFIG、INFO、WARNING、SEVERE、OFF这九个级别,与通常的日志框架分类法不太一样),MyBatis统一提供trace、debug、warn、error四个级别,这基本与主流框架分类法是一致的(相比而言缺少Info,也许MyBatis认为自己的日志要么是debug需要的,要么就至少是warn,没有Info的必要)。

在org.apache.ibatis.logging里还有个比较特殊的包jdbc,这不是按字面意义理解把日志通过jdbc记录到数据库里,而是将jdbc操作以开发者配置的日志框架打印出来,这也就是我们在开发阶段常用的跟踪SQL语句、传入参数、影响行数这些重要的调试信息。

3.2、IO

MyBatis里的IO主要是包含两大功能:提供读取资源文件的API、封装MyBatis自身所需要的ClassLoader和加载顺序。

3.3、reflection

在MyBatis如参数处理、结果映射这些大量地使用了反射,需要频繁地读取Class元数据、反射调用get/set,因此MyBatis提供了org.apache.ibatis.reflection对常见的反射操作进一步封装,以提供更简洁方便的API。比如我们reflect时总是要处理异常(IllegalAccessException、NoSuchMethodException),MyBatis统一处理为自定义的RuntimeException,减少代码量。

3.4、exceptions

在以Spring为代表的开源框架中,对于应用程序中无法进一步处理的异常大都转成RuntimeException来方便调用者操作,另外如频繁遇到的SQLException,JDK约定其是个Exception,从JDK的角度考虑,强制要求开发者捕获SQLException是为了能在catch/finally中关闭数据库连接,而Spring之类的框架为开发者做了资源管理的事情,自然就不需要开发者再烦心SQLException,因此封装转换成RuntimeException。MyBatis的异常体系不复杂,org.apache.ibatis.exceptions下就几个类,主要被使用的是PersistenceException。

3.5、缓存

缓存是MyBatis里比较重要的部分,有两种缓存:

  • SESSION或STATEMENT作用域级别的缓存,默认是SESSION,BaseExecutor中根据MappedStatement的Id、SQL、参数值以及rowBound(边界)来构造CacheKey,并使用BaseExccutor中的localCache来维护此缓存。
  • 全局的二级缓存,通过CacheExecutor来实现,其委托TransactionalCacheManager来保存/获取缓存,这个全局二级缓存比较复杂,后面还需要专题分析,至于其缓存的效率以及应用场景也留到那时候再分析。

3.6、数据源/连接池

MyBatis自身提供了一个简易的数据源/连接池,在org.apache.ibatis.datasource下,后面专题分析。主要实现类是PooledDataSource,包含了最大活动连接数、最大空闲连接数、最长取出时间(避免某个线程过度占用)、连接不够时的等待时间,虽然简单,却也体现了连接池的一般原理。阿里有个“druid”项目,据他们说比proxool、c3p0的效率还要高,可以学习一下。

3.7 事务

MyBatis对事务的处理相对简单,TransactionIsolationLevel中定义了几种隔离级别,并不支持内嵌事务这样较复杂的场景,同时由于其是持久层的缘故,所以真正在应用开发中会委托Spring来处理事务实现真正的与开发者隔离。分析事务的实现是个入口,借此可以了解不扫JDBC规范方面的事情。

后续将对MyBatis各个部分做详细的设计及源代码分析,由于读取和解析SqlMapConfig.xml和SqlMap.xml的逻辑与各个模块的相关性较强,因此将把这部分内容与在各模块组合在一起分析。

感谢本文原创作者,但是木有找到。。。

MyBatis架构(转)的更多相关文章

  1. Mybatis架构学习

    Mybatis架构学习 MyBatis 是支持定制化 SQL.存储过程以及高级映射的持久层框架.MyBatis 封装了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.可以对配置和原生Map使用 ...

  2. 《深入了解mybatis原则》 MyBatis架构设计和案例研究

    MyBatis这是现在很流行ORM框架,这是非常强大.事实上现却比較简单.优雅. 本文主要讲述MyBatis的架构设计思路,而且讨论MyBatis的几个核心部件.然后结合一个select查询实例.深入 ...

  3. SpringMVC,Spring,Hibernate,Mybatis架构开发搭建之SpringMVC部分

    SpringMVC,Spring,Hibernate,Mybatis架构开发搭建之SpringMVC部分 辞职待业青年就是有很多时间来写博客,以前在传统行业技术强度相对不大,不处理大数据,也不弄高并发 ...

  4. Mybatis架构简介

    一.Mybatis与ORM 对象关系映射(即Object Relational Mapping,简称ORM),主要用于关系型数据库和实体之间的映射,主要为了解决对象与关系数据库存在的互不匹配的现象,O ...

  5. (转)MyBatis框架的学习(二)——MyBatis架构与入门

    http://blog.csdn.net/yerenyuan_pku/article/details/71699515 MyBatis框架的架构 MyBatis框架的架构如下图: 下面作简要概述: S ...

  6. (五)myBatis架构以及SQlSessionFactory,SqlSession,通过代理执行crud源码分析---待更

    MyBatis架构 首先MyBatis大致上可以分为四层: 1.接口层:这个比较容易理解,就是指MyBatis暴露给我们的各种方法,配置,可以理解为你import进来的各种类.,告诉用户你可以干什么 ...

  7. 二 Mybatis架构&MybatisDao的两种开发方式(原始Dao,接口动态代理)

    MyBatis架构图 三个对象: SqlSessionFactoryBuilder.SqlSessionFactory.SqlSession SqlSessionFactoryBuilder:主要用来 ...

  8. MyBatis(十一):MyBatis架构流程浅析

    架构分层 我们将MyBatis架构分为三层,分别为接口层.数据处理层和框架支撑层 接口层:提供外部接口调用的API,使用端通过这些API来操作数据库,接口层收到请求后会调用数据处理层完成具体的数据处理 ...

  9. Mybatis架构原理(二)-二级缓存源码剖析

    Mybatis架构原理(二)-二级缓存源码剖析 二级缓存构建在一级缓存之上,在收到查询请求时,Mybatis首先会查询二级缓存,若二级缓存没有命中,再去查询一级缓存,一级缓存没有,在查询数据库; 二级 ...

随机推荐

  1. js判断鼠标进入以及离开容器的方向

      (注:以下代码涉及到jQuery,建议前端大牛绕路~~~) 1.遇到的问题      如图当鼠标右箭头位置上下移动的时候  下面的城市列表容器不能隐藏. 2.方法: 网上搜了些前端大牛们的解决办法 ...

  2. Shell 语法之函数

    函数是被赋予名称的脚本代码块,可以在代码的任意位置重用.每当需要在脚本中使用这样的代码块时,只需引用该代码块被赋予的函数名称. 创建函数 格式 function name { commands } n ...

  3. Windows下安装postgresql_psycopg2时出现 "Unabled to find vcvarsall.bat" 的解决办法

    使用django时会用到postgresql的数据库,如下表: 数据库引擎设置 设置 数据库 适配器 postgresql PostgreSQL psycopg 版本 1.x, http://www. ...

  4. 再谈 Unlix (Linux, AIX, HPUX) 上 Java 的 java.lang.OutOfMemoryError: unable to create new native thread

    首先很容易排除是 程序问题 内存用了很少,64 位 Java也没有内存限制,线程也不多,-Xss 堆栈也没人会配置很大. 那么肯定是 limit 不足引起 配置 ulimit 就可以了,问题看起来很简 ...

  5. [分享] RT7LITE精简后无法封装解决办法

    eagleonly 发表于 2016-6-9 11:00:01  https://www.itsk.com/forum.php?mod=viewthread&tid=368090&hi ...

  6. float浮动深入理解

    [CSS深入理解之float浮动]听课总结 (http://www.imooc.com/learn/121)   1.float的原本作用:为了实现文字环绕 2.float的包裹性和破坏性: 包裹性: ...

  7. qt5.4.0在windows,32位下的编译, vs2010平台

    假设源代码入在D:\3DFrame\qt-everywhere-opensource-src-5.4.0\qt-everywhere-opensource-src-5.4.0 1:首先从官方网站下载源 ...

  8. jQuery实现滚动效果详解1

    声明:第一次写原创,本人初学,很多地方一知半解,本篇算是一个学习的笔记,欢迎批评指正,转载请注明. 今天要做的效果是在网上经常能看到多幅图片向左无缝滚动,鼠标滑过动画暂停,鼠标滑出动画继续的效果.网上 ...

  9. Android开发--FrameLayout的应用

    1.简介 frameLayout为框架布局,该布局的特点为层层覆盖,即最先放置的部件位于最下层,最后放置的部件位于最上层. 2.构建 如图所示,该视图中有五个TextView.其中,tv1放置在最底层 ...

  10. 分布式系统中一些主要的副本更新策略——Dynamo/Cassandra/Riak同时采取了主从式更新的同步+异步类型,以及任意节点更新的策略。

    分布式系统中一些主要的副本更新策略. 1.同时更新 类型A:没有任何协议,可能出现多个节点执行顺序交叉导致数据不一致情况. 类型B:通过一致性协议唯一确定不同更新操作的执行顺序,从而保证数据一致性 2 ...