最近查找一个生产问题的原因,需要深入研究 ibatis 框架的源码。虽然最后证明问题的原因与 ibatis 无关,但是这个过程加深了对 ibatis 框架原理的理解。

这篇文章主要就来讲讲 ibatis 框架的原理。

可能现在很多人已不再使用 ibatis 或者说也没听 ibatis,不过肯定了解过 Mybatis。ibatis 就是 Mybatis框架的前身,虽然 ibatis 框架已经比较老,但是其核心功能与 Mybatis 一致。

ibatis 解决的痛点

我们先看一个使用 JDBC 查询的例子。

使用原生 JDBC 查询,存在两个痛点:

  1. 使用非常繁琐,且需要处理各种数据库异常,并且还需要关闭各种资源。
  2. 数据转化麻烦。查询之前需要从 Java 对象属性值设置到 PreparedStatement中,查询返回之后又需要从 ResultSet获取返回设置到返回对象中。

在 ibatis 中封装这些繁杂数据库连接查询代码,并处理了各类异常以及关闭各种资源。另外 ibatis 自动处理 Java 对象与数据库类型之间的自动转化,让业务代码与 SQL 代码之间做到了解耦。

数据类型转化原理

数据类型转化主要分为两类,一,传入查询的 Java 对象数据转化成 SQL 类型数据。二 查询返回的数据库信息映射到 Java 对象中。

ibatis SQL 需要定义在配置文件中,一个查询 SQL 语句配置如下:

<select id="queryName" parameterClass="com.query.QueryDO"  resultClass="com.query.QueryDO" >select  * from  TEST_QUERY where ID=#id#</select>

ibatis 框架启动过程将会解析配置文件,生成 MappedStatement 的子类。如 select 配置会生成对应的 SelectStatement 对象。

MappedStatement 相关类图如下。

MappedStatement 中将会保存存在两个重要的对象,ParameterMapResultMap,通过这两个对象将会完成 Java 类型与数据库类型的相互转化。

Java 对象转化成数据库类型

以上面 select 配置为例,我们这里需要做的是从传入的 com.query.QueryDO对象中获取属性值,然后通过 PreparedStatement.setxx 设置到查询参数中。

ibatis 解析配置中 SQL 语句时,将会获取 # 之间的内容,将其替换成 ?。然后按照顺序保存到一个 ParameterMapping[] 数组中,这个数组将会保存到 ParameterMap 对象中。

ParameterMapping 将会保存解析字段相关信息。

最终解析后的 SQL 为:


select  * from  TEST_QUERY where ID=?

该 SQL 就可以通过 connection.prepareStatement("select * from TEST_QUERY where ID=?"); 生成 PreparedStatement 对象。

接着 ibatis 会根据 ParameterMappingparameterClass指定的类型创建合适的 dataExchangeparameterPlan对象。

其中 parameterPlan 对象会按照 ParameterMapping数组中顺序保存了变量的 setter 和 getter 方法数组。

dataExchange会按照 ParameterMapping 数组中的顺序使用反射获取 parameterPlan getter 方法返回值生成 parameters 数组。

最后循环 ParameterMapping 数组,在 TypeHandler 调用 PreparedStatement.setxx 设置相关值。

TypeHandler 存在很多子类,通过这些子类正确处理了 Java 对象与数据库类型转化。

转化的时序图为:

时序图来源于:https://www.ibm.com/developerworks/cn/java/j-lo-ibatis-principle/index.html

数据库字段映射到 Java 对象

SQL 执行结束之后将会返回查询结果,这里将会使 SQL 查询结果转化为返回结果 com.query.QueryDO。这里需要用到上面提到 ResultMap 对象。

当 SQL 执行结束返回 ResultSet 对象之后,使用 ResultSet.getMetaData() 获取返回信息元数据对象 ResultSetMetaData

ResultSetMetaData 可以获取返回结果字段名,类型等信息,然后按照顺序存入 ResultMapping 数组中。

然后按照 ResultMapping 数组中使用 TypeHandler调用 ResultSet.getxx 获取实际返回数据,保存到 columnValues 数组中。

ResultMap 对象会根据 ResultMappingresultClass指定的类型合适的 dataExchangeresultPlan对象。resultPlan对象与上面的 parameterPlan对象一样也会保存着变量的 setter 和 getter 方法数组。

最后先根据 resultClass 反射生成返回对象,然后使用反射调用 resultPlan setter 方法,依次设置相关值。

映射返回对象时序图为:

时序图来源于:https://www.ibm.com/developerworks/cn/java/j-lo-ibatis-principle/index.html

ibatis 样板代码

上面讲完了 ibatis 数据类型的转化原理,接着我们来看下 ibatis 调用 JDBC 样板代码。

使用 ibatis 执行查询语句时,如 queryForObject,调用到 SqlMapExecutorDelegate 。在 SqlMapExecutorDelegate 中将会会做一些前提准备,比如准备事务,最后会将 SQL 语句委托给 SqlExecutor 执行。

这里使用委托者模式,接受请求的对象将请求委托给另一个对象来处理。这种模式的优点在于解耦了业务代码与实际执行代码的联系,在于对外隐藏真正执行对象,易于扩展。

SqlExecutor#executeQuery 执行过程主要分为以下三步。

第一步,获取 PreparedStatement,使用 conn.prepareStatement(sql) 获取。

第二步调用 PreparedStatement.setxxx 方法设置参数。上文中的 Java 对象类型转化成 SQL 类型在这里完成。

第三步,调用 PreparedStatement.execute() 执行 SQL 语句。

第四步,使用 ResultSet 获取返回值,在这一步将会完成 数据库类型与 Java 类型的转化。

帮助链接

深入分析 iBATIS 框架之系统架构与映射原理

ibatis 核心原理解析相关推荐

  1. MyBatis的运行的核心原理解析(三)

    2019独角兽企业重金招聘Python工程师标准>>> #插件 四大对象在运行得时候,在Configuration对象得创建方法里MyBatis使用了责任链得方式去封装,也就是说我们 ...

  2. 【Spring】1.核心原理解析

      目录 概况 Bean的生命周期 推断构造方法 AOP流程 事务 概况 核心知识点串讲,对Spring有整体的了解 比如: 1. Bean的生命周期原理 2. 依赖注入原理 3. 初始化原理 4. ...

  3. spring源码分析01-(前期准备)spring核心原理解析和手写简易spring

    1.本文主要介绍内容 本文会把Spring中核心知识点大概解释下.可以对Spring的底层有一个整体的大致了解.主要内容包括: 手写简易spring框架,帮助更好理解spring. 代码点击链接自取 ...

  4. Spring框架(一) 底层核心原理解析

    感兴趣的话大家可以关注一下公众号 : 猿人刘先生 , 欢迎大家一起学习 , 一起进步 , 一起来交流吧! 说明 本系列文章以spring-framework-5.3.10为例 , 本篇文章的目的就是使 ...

  5. 【Spring】Spring底层核心原理解析

    本文内容索引: 1.Bean的生命周期底层原理 2.依赖注入底层原理 3.初始化底层原理 4.推断构造方法底层原理 5.AOP底层原理 6.Spring事务底层原理 ​但都只是大致流程,后续会针对每个 ...

  6. Spring源码学习(一)--Spring底层核心原理解析

    目录 Spring中是如何创建一个对象? Bean的创建过程 推断构造方法 AOP大致流程 Spring事务 最近在跟视频学习spring源码,将每节课记录下来,以后好来复习. 首先把Spring中核 ...

  7. react 流程图框架_【赠书】Preact(React)核心原理详解Preact(React) 核心原理解析...

    豆皮粉儿们,又见面了,今天这一期,由字节跳动数据平台的"winge(宝丁)",带大家见识见识前端"轮子"之一Preact框架. 提到Preact,你肯定会先想到 ...

  8. Spring学习篇底层核心原理解析

    说明 本系列文章以spring-framework-5.3.10为例 ,本篇文章的目的就是使各位读者能在使用Spring的基础上对Spring的一些比较核心的内容有一个大概的认识,并不是特别全面,会在 ...

  9. Nginx的核心原理解析

    Nginx 反向代理VS正向代理: 反向代理服务器对于客户端而言它就像是原始服务器,并且客户端不需要进行任何特别的设置.客户端向反向代理的命名空间(name-space)中的内容发送普通请求,接着反向 ...

  10. Alibaba史上最牛的分布式核心原理解析全彩手册开源,称霸GitHub

    学习是一种基础性的能力.然而,"吾生也有涯,而知也无涯.",如果学习不注意方法,则会"以有涯随无涯,殆矣". 学习就像吃饭睡觉一样,是人的一种本能,人人都有学习 ...

最新文章

  1. (转)PHP框架大比武
  2. Java的ArrayList集合_JAVA之ArrayList集合
  3. SpringSide 4 QuickStart运行Demo
  4. 博客园T恤内部泄漏版(附图)
  5. 【矩阵乘法】【倍增】美食家(luogu 6772)
  6. 修复mysql的view_MYSQL数据损坏修复方法
  7. kali 安装grub theme
  8. 关于iOS13 的一些适配
  9. HDF5: Python 的h5py与Julia的HDF5库读取效率比较,不差上下
  10. 10、斐波那契数列,跳台阶问题(Python)
  11. NSGA-Ⅱ算法原理
  12. 免费下载 | 秒变钉钉应用开发达人!《钉钉应用开发者速成手册》独家上线
  13. 基于51单片机的智能时控开关设计
  14. Unity编辑器修改图片的大小
  15. 苹果开发者账户续费 支付授权失败(终极解决方案)
  16. ModelSim illegal reference to net “***“ 报错问题解决
  17. HCIA-RoutingSwitching华为认证路由交换工程师(持续更新中2%)
  18. Dubbo host配置映射内网IP导致消费者无法连接到生产者提供的服务详解
  19. 详解VMware12安装Mac OS X 10.11
  20. 大三计算机保研er现在还能参加哪些竞赛?

热门文章

  1. appium python api
  2. Facebook团队关于网页缓存的再实践
  3. MediaChooser图库浏览器
  4. 如何将MyEclipse开发的项目导入到Eclipse中运行
  5. [导入]SQL Server 索引基础知识(4)----主键与聚集索引
  6. OpenGl 游戏编程笔记 第七章:纹理映射 (texture mapping) (一)
  7. HDU 1465 不容易系列之一 (错排)
  8. 拓端tecdat|R语言分布滞后非线性模型(DLNM)研究发病率,死亡率和空气污染示例
  9. 拓端tecdat|R语言对NASA元数据进行文本挖掘的主题建模分析
  10. 拓端tecdat|通过Python中的Apriori算法进行关联规则挖掘