ibatis 核心原理解析!
关注下方公众号,可以在公众号后台回复“博客园”,免费获得作者 Java 知识体系/面试必看资料。
最近查找一个生产问题的原因,需要深入研究 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#
ibatis 框架启动过程将会解析配置文件,生成 MappedStatement 的子类。如 select 配置会生成对应的 SelectStatement 对象。
MappedStatement 相关类图如下。
在 MappedStatement 中将会保存存在两个重要的对象,ParameterMap 与 ResultMap,通过这两个对象将会完成 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 会根据 ParameterMapping 和 parameterClass 指定的类型创建合适的 dataExchange 和 parameterPlan 对象。
其中 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 对象会根据 ResultMapping 与 resultClass指定的类型合适的 dataExchange 和 resultPlan对象。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 类型的转化。
帮助链接
References
[1] 深入分析 iBATIS 框架之系统架构与映射原理: https://www.ibm.com/developerworks/cn/java/j-lo-ibatis-principle/index.html
欢迎长按下图关注公众号Java极客技术,后台回复“资料”,获取作者独家秘制精品资料
Java 极客技术公众号,是由一群热爱 Java 开发的技术人组建成立,专注分享原创、高质量的 Java 文章。如果您觉得我们的文章还不错,请帮忙赞赏、在看、转发支持,鼓励我们分享出更好的文章。
ibatis 核心原理解析!的更多相关文章
- ibatis 核心原理解析
最近查找一个生产问题的原因,需要深入研究 ibatis 框架的源码.虽然最后证明问题的原因与 ibatis 无关,但是这个过程加深了对 ibatis 框架原理的理解. 这篇文章主要就来讲讲 ibati ...
- 【算法】(查找你附近的人) GeoHash核心原理解析及代码实现
本文地址 原文地址 分享提纲: 0. 引子 1. 感性认识GeoHash 2. GeoHash算法的步骤 3. GeoHash Base32编码长度与精度 4. GeoHash算法 5. 使用注意点( ...
- Java并发包JUC核心原理解析
CS-LogN思维导图:记录CS基础 面试题 开源地址:https://github.com/FISHers6/CS-LogN JUC 分类 线程管理 线程池相关类 Executor.Executor ...
- 「进阶篇」Vue Router 核心原理解析
前言 此篇为进阶篇,希望读者有 Vue.js,Vue Router 的使用经验,并对 Vue.js 核心原理有简单了解: 不会大篇幅手撕源码,会贴最核心的源码,对应的官方仓库源码地址会放到超上,可以配 ...
- Promise核心原理解析
作者: HerryLo 本文永久有效链接: https://github.com/AttemptWeb...... Promises对象被用于表示一个异步操作的最终完成 (或失败), 及其结果值.主要 ...
- NameServer 核心原理解析
在之前的文章中,已经把 Broker.Producer 和 Conusmer 的部分源码和核心的机制介绍的差不多了,但是其实 RocketMQ 中还有一个比较关键但是我们平时很容易忽略的组件--Nam ...
- 【转】GeoHash核心原理解析
好久没更新过博客了,先转载一篇文章吧. 源地址:http://www.cnblogs.com/LBSer/p/3310455.html 引子 机机是个好动又好学的孩子,平日里就喜欢拿着手机地图点点按按 ...
- GeoHash核心原理解析
http://www.cnblogs.com/LBSer/p/3310455.html 引子 机机是个好动又好学的孩子,平日里就喜欢拿着手机地图点点按按来查询一些好玩的东西.某一天机机到北海公园游玩, ...
- [转]GeoHash核心原理解析
原文出处: zhanlijun 引子 机机是个好动又好学的孩子,平日里就喜欢拿着手机地图点点按按来查询一些好玩的东西.某一天机机到北海公园游玩,肚肚饿了,于是乎打开手机地图,搜索北海公园附近的餐 ...
随机推荐
- java 中的一些运算符问题
逻辑运算符 && 与 &: 在这二个与运算符中,一般用于if的判断中,A&&B,假设A的条件不满足时 则不会去判断后面的B, 如果A满足条件时就会接下来去做B条 ...
- 深扒那些艺术的CSS
概览 使用单个div做css绘图,会充分利用到: before.after伪元素 使用border-radius.border来控制图形的形状. 使用叠加的box-shadow来创建多个相同的形状(可 ...
- 精通并发与 Netty (二)常用的 rpc 框架
Google Protobuf 使用方式分析 对于 RPC 协议来说,最重要的就是对象的发送与接收,这就要用到序列化与反序列化,也称为编码和解码,序列化与反序列化和网络传输一般都在对应的 RPC 框架 ...
- mysql-8.0.16-winx64/Linux修改root用户密码
连接数据库等基础操作请自行解决哈,本篇是重点记录如何改密码. 一.查询用户密码: 查询用户密码命令: select host, user, authentication_string from mys ...
- Azkaban Flow 2.0 使用简介
官方建议使用Flow 2.0来创建Azkaban工作流,且Flow 1.0将被弃用 目录 目录 一.简单的Flow 1. 新建 flow20.project 文件 2. 新建 .flow 文件 3. ...
- flask 高级编程 上下文与栈(转)
转: https://www.cnblogs.com/wangmingtao/p/9372611.html 22.上下文与出入栈 22.1 请求过程 请求过来,flask会实例化一个Request C ...
- 控制台程序秒变Windows服务(Topshelf)
项目中有些时候需要写服务,一般我们都是先创建控制台程序,测试,运行,成功之后再创建windows服务程序,这样好麻烦啊,有没有简单的控制台程序直接变成Widnows服务,经过查找,找到了Topshel ...
- linux学习书籍推荐《鸟哥的Linux私房菜》下载
下载地址:点我 <鸟哥的Linux私房菜:基础学习篇>是具有知名度的Linux入门书<鸟哥的Linux私房菜基础学习篇>的最新版,全面而详细地介绍了Linux操作系统.< ...
- Coder必须自废的两样神功
Coder必须自废的两样神功 大理段氏以一阳指神功驰名天下.奉六脉宝经,立天龙佛院:凭借数百载基业威名,与嵩山少林.终南全真分庭抗礼:乃宋代中华武术三大派系之一. 二指禅是一种鲜为人知的秘传功法,通过 ...
- springcloud-eureka客户端服务注册(含demo源码)
1. 场景描述 前几天介绍了下springcloud的Eureka注册中心(springcloud-注册中心快速构建),今天结合springboot-web介绍下eureka客户端服务注册. 2. 解 ...