ibatis 核心原理解析_ibs架构
wptr33 2025-09-24 05:00 53 浏览
最近查找一个生产问题的原因,需要深入研究 ibatis 框架的源码。虽然最后证明问题的原因与 ibatis 无关,但是这个过程加深了对 ibatis 框架原理的理解。
这篇文章主要就来讲讲 ibatis 框架的原理。
可能现在很多人已不再使用 ibatis 或者说也没听 ibatis,不过肯定了解过 Mybatis。ibatis 就是 Mybatis框架的前身,虽然 ibatis 框架已经比较老,但是其核心功能与 Mybatis 一致。
ibatis 解决的痛点
我们先看一个使用 JDBC 查询的例子。
使用原生 JDBC 查询,存在两个痛点:
- 使用非常繁琐,且需要处理各种数据库异常,并且还需要关闭各种资源。
- 数据转化麻烦。查询之前需要从 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 中将会保存存在两个重要的对象,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 类型的转化。
相关推荐
- oracle数据导入导出_oracle数据导入导出工具
-
关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...
- 继续学习Python中的while true/break语句
-
上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个...
- python continue和break的区别_python中break语句和continue语句的区别
-
python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...
- 简单学Python——关键字6——break和continue
-
Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...
- 2-1,0基础学Python之 break退出循环、 continue继续循环 多重循
-
用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...
- Python 中 break 和 continue 傻傻分不清
-
大家好啊,我是大田。...
- python中的流程控制语句:continue、break 和 return使用方法
-
Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...
- L017:continue和break - 教程文案
-
continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...
- 作为前端开发者,你都经历过怎样的面试?
-
已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...
- 面试被问 const 是否不可变?这样回答才显功底
-
作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...
- 2023金九银十必看前端面试题!2w字精品!
-
导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。...
- 前端面试总结_前端面试题整理
-
记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...
- 由浅入深,66条JavaScript面试知识点(七)
-
作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录...
- 2024前端面试真题之—VUE篇_前端面试题vue2020及答案
-
添加图片注释,不超过140字(可选)...
- 今年最常见的前端面试题,你会做几道?
-
在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...
- 一周热门
- 最近发表
-
- oracle数据导入导出_oracle数据导入导出工具
- 继续学习Python中的while true/break语句
- python continue和break的区别_python中break语句和continue语句的区别
- 简单学Python——关键字6——break和continue
- 2-1,0基础学Python之 break退出循环、 continue继续循环 多重循
- Python 中 break 和 continue 傻傻分不清
- python中的流程控制语句:continue、break 和 return使用方法
- L017:continue和break - 教程文案
- 作为前端开发者,你都经历过怎样的面试?
- 面试被问 const 是否不可变?这样回答才显功底
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)
