闻与MyBatis之MyBatis解析 Mappe 原理

本文内容如有错误、不足之处,欢迎技术爱好者们一同探讨,在本文下面讨论区留言,感谢。欢迎转载,转载请注明出处(https://blog.csdn.net/feng_xiaoshi/article/details/106268334),谢谢。

简介

mybatis’s mapper principle
使用 Mybatis 是否有 Mybatis 的核心成分是什么?它在做什么?Mybatis 仅添加了接口类,没有实现类,为什么可以直接查询?等等的疑问,今天就深入 Mybatis 代码,探索 MyBatis 世界。

MyBatis设计框架
代码框架

代码包结构图

抽象框架
  • 接口层
  • 数据处理层
  • 底层支撑层
  • 启动层
核心组件
类名作用
SqlSessionMyBatis 关键 API,和数据库交互会话,执行数据库crud操作的核心
ExecutorMyBatis 执行器,是 MyBatis 调度协调程序的核心,负责 SQL 语句的生成和查询缓存的维护
StatementHandler封装JDBC语句操作,负责JDBC语句的操作,例如如何设置参数,将执行结果集放入列表集合中。
ParameterHandler参数处理器,负责处理接口的入参的参数,以转换 Statement JDBC 所需的参数,
ResultSetHandler返回结果集处理器,负责将 JDBC 返回的 ResultSet 结果集对象转换为 List 类型的集合。
TypeHandler负责Java数据类型和JDBC数据类型之间的映射和转换,主要由其子对象实现,例如 StringHandler 负责处理 String 类型转换
MappedStatementMappedStatement 负责 select 、update 、 delete 、insert 标签的封装,
SqlSource根据调用者的 parameterObject 实现转换,动态生成SQL语句,将信息封装到 BoundSql 对象,然后返回。
BoundSql表示动态生成的SQL语句以及相应的参数信息
ConfigurationMyBatis的所有配置信息都保存在Configuration对象中。
运行原理
分析流程图
创建 SqlSessionFactory 和 SqlSession

xml读取信息创建 sessionFactoryBuilder sqlSession

创建 MapperProxy

创建 MapperProxy

执行 sql 操作

执行 sql 操作

分析解剖

现在进行代码分析、逻辑解剖:

整个测试流程总共分为三步,分别对应上面流程图:

第一步:构建 SqlSessionFactoryBuilder ,通过 SqlSessionFactoryBuilder 创建 SqlSessionFactory 对象,进而通过 SqlSessionFactory 创建 SqlSession 对象,此过程中,每个解析的文件都存储在 Configuration 中,返回的 SqlSessionFactory 属于 DefaultSqlSessionFactory,在创建 SqlSession 对象过程中将创建一个Executor对象,还涉及 MappedStatement 包含 insertdeletedupdate 的详细信息。
第二步:构建接口的代理对象 MapperProxy,通过 MapperProxyFactory 进行创建代理对象,包含代理对象。
第三步:执行增删改查方法,此过程中涉及 BoundSqlsql 生成。

第一步

在这里插入图片描述
InputStream inputStream = Resources.getResourceAsStream(resource); 读取到的输入流传入 build 方法中,生成 DefaultSqlSessionFactory 对象。

调用 build 方法逻辑:
在这里插入图片描述
XMLConfigBuilder 配置构建器:
分析 XMLConfigBuilder 源码可以发现在 mybatis 的注释中,包含了 issue 修改编号的记录,针对 117 编号的 issue 找到了问题原因,而且由于后来代码维护和修改,代码的实际逻辑和 issue 的问题出入很大,而且针对 issue 631 的问题与代码不符,如果有哪位师兄知道具体原因可以留言一起探究。
XmlConfugBuilder
调用 build() 方法,获取 DefaultSqlSessionFactory
SqlSessionFactoryBuilder 提供了大量的 build() 方法,主要是供配置信息转换到 mybatis 上下文当中,供 BoundSqlSqlSession 获取需要的信息。
build
DefaultSqlSessionFactory#openSession() :
DefaultSqlSessionFactory
调用获取新执行器的方法:
在这里插入图片描述
返回的 DefaultSqlSession 包含了全局配置和执行器:
在这里插入图片描述

第二步

第二步的关注点是如何通过反射来获取 MapperProxy,一起走进代码逻辑:
首先是 DefaultSqlSession 调用 getMapper 方法:
在这里插入图片描述

这个方法调用的是全局配置的 getMapper 方法:
在这里插入图片描述
Configuration#getMapper 调用 MapperRegistry#getMapper

在这里插入图片描述

MapperRegistry 方法中通过创建 MapperProxyFactory 来构建一个 MapperProxy 实例,MapperProxy 是一个 InvocationHandlerInvocationHandler 作用是: Mybatis 初始化的时候扫描包路径,以及配置路径,以及如何将 Java MapperXML Mapper 映射起来, 原理就是使用 JDK 动态代理(cglib) 构建代理类,InvocationHandler就是这个JDK 动态代理。
MapperProxyFactory 创建 MapperProxy
在这里插入图片描述
注意: 代码中调用 Proxy#newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h) 此方法返回指定的接口的代理类的实例方法调用指派到指定的调用处理程序,因此 Mybatis 通过反射将 Mapper 接口和对应的 XML 配置文件信息代理一个对应的 Mapper 接口的实体类。

MapperProxy 源码:
MapperProxy 源码

第三步

有了对应的接口实体,下一步就是执行对应的 Sql 语句。
调用 MapperProxy#invoke,生成代理对象就是执行 invoke方法,才会执行相应的被代理对象的方法:
invoke 方法
execute方法的逻辑:
execute 方法
重点分析 selectOne 方法的逻辑:
在代码中可以发现 selectOne 调用了 selectList ,判断 selectList 返回的数据条数大于 1 抛出异常,如果为空抛出 null
selectOne
selectList 查询,进入 XML 配置中 sql 语句执行的核心:
selectList
DynamicSqlSource#getBoundSql(Object parameterObject)方法,返回一个 BoundSql 对象。一个 BoundSql 对象,代表了一次sql语句的实际执行,而 SqlSource 对象的责任,就是根据传入的参数对象,动态计算出这个 BoundSql
query 方法
BaseExector: 基础执行器,封装了子类的公共方法,包括一级缓存、延迟加载、回滚、关闭等功能.
baseExecutor#query
CahceKeykey 的格式:影响因子的 HashCode1:影响因子的 HashCode2:方法ID:offset:limit:SQL语句:参数:环境ID
-1123117942:1738479101:com.feng.UserMapper.selectUser:0:2147483647:select * from user where id = ? :1:emma:0:dev

CacheKey
通过路由 RoutingStatementHandler 来获取真实使用的 StatementHandler
RoutingStatementHandler

总结

这篇文章只是简单描述一下 Mybatis 的运行原理,以及类的作用说明,当然还有许多细节和类没有介绍,Mybatis中的设计模式和架构思路都是值得学习。

参考资料
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值