MyBatis源码分析_ResultSetHandler(7)

这篇具有很好参考价值的文章主要介绍了MyBatis源码分析_ResultSetHandler(7)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1. 传统JDBC

2. Mybatis访问数据库

2.1  Statement访问数据库

2.2  火枪手 ResultSetHandler 出现

3. ResultSetHandler处理结果集

3.1 首先就是进入 handleResultSets 方法

3.2 handleResultSet 方法根据映射规则(resultMap)对结果集进行转化

3.3 handleRowValuesForSimpleResultMap 方法对行进行映射处理

4.  getRowValue方法针对读取ResultSet对象进行映射(3.3细化)

4.1 根据resultMap的type属性,实例化目标对象

4.2 对目标对象进行封装得到metaObjcect,为后续的赋值操作做好准备

4.3一般情况下 autoMappingBehavior默认值为PARTIAL,对未明确指定映射规则的字段进行自动映射

4.4 映射resultMap中明确指定需要映射的列

4.5 如果没有一个映射成功的属性,则根据的配置返回null或者结果对象

5. 保存映射结果对象

5.1  resultContext 计数作用

 5.2 ResultHandler存储结果集

6. 主流程over


1. 传统JDBC

Mybatis其实就是封装传统JDBC的,它和传统JDBC访问数据库基本一模一样。因此,不要觉得Mybatis有多高级。而 ResultSetHandler 就是处理我们JDBC访问数据库获取到的ResultSet结果集的。在此之前,我们还是先看一下传统JDBC:

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

再次基础之上,我们继续分析Mybatis是如何访问数据库并且封装对象的。

2. Mybatis访问数据库

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

中间涉及到设置参数,初始化Statement等操作,这些在MyBatis源码分析_Executor组件及3个火枪手(6)_chen_yao_kerr的博客-CSDN博客已经 分析过了。接下来将是直接分析访问数据库以及返回结果集的处理。

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

最终,他会调用到 RoutingStatementHandler的query方法。而我们在实例化RoutingStatementHandler的时候,我们说过它是典型的策略模式。它是根据xml配置文件的信息,生成不同的StatementHandler对象,而本文则是基于PreparedStamentHandler进行的,因此它必然会进入PreparedStamentHandler的query方法:

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

 MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

2.1  Statement访问数据库

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

最终调用的是mysql的底层jar包PreparedStatementLogger对象访问的数据库,这一点和JDBC访问的方式一模一样,我们就不做过多的分析了。

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

2.2  火枪手 ResultSetHandler 出现

访问数据库结束以后,我们会对调用ResultSetHandler对象对结果集进行mybatis特有的处理,这一点是和JDBC不同的:

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

而 StatementHandler 的基类中,是持有ResultSetHandler的:

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

 所有,我们的PreparedStatementHandler才可以直接使用ResultSetHandler对象处理结果集ResultSet.

3. ResultSetHandler处理结果集

3.1 首先就是进入 handleResultSets 方法

a. 首先就是从Statement对象中获取第一个结果集ResultSet并包装成 ResultSetWrapper

b. 获取结果集对应的ResultMap,这个是在第一阶段加载xml文件的时候就准备好的,column-property的形式

c. 根据映射规则(resultMap)对结果集进行转化,转换成目标对象以后放入multipleResults中

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

d. 获取下一个结果集继续遍历,直到遍历完所有的结果集位置。

3.2 handleResultSet 方法根据映射规则(resultMap)对结果集进行转化

其实,这个方法就是对结果集进行缓存处理,并且在填充完以后放入list中。

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

3.3 handleRowValuesForSimpleResultMap 方法对行进行映射处理

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

针对读取ResultSet对象进行映射并且保存映射结果,我将单独开一个大的段落进行分析。本篇后面的所有内容都是针对此处进行详细分析。

4.  getRowValue方法针对读取ResultSet对象进行映射(3.3细化)

首先看一下getRowValue方法的总体结构,后面将针对这个结果逐步分析每一步都干了什么事情

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

4.1 根据resultMap的type属性,实例化目标对象

这一步挺简单的,就是根据我们配置的返回值类型,实例化出来一个空的对象,方便后面的步骤进行值的设置

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

4.2 对目标对象进行封装得到metaObjcect,为后续的赋值操作做好准备

元数据对象,由Configuration对象负责生成,它是mybatis提供的反射工具类。因为这是一个底层代码,使用反射设置属性值是通用做法,而传统的java反射对处理List、Map、嵌套类等处理起来并不方便。而Mybatis提供的MetaObject对象,能够很好的处理集合、嵌套类等,功能更为强大。

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

生成对象以后,我们来看一下这个结构:

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

由于我们的测试case不涉及嵌套类型的查询,因此无法看到嵌套类型具体值的设置过程,后面会补一篇关于嵌套类型的博客,单独进行分析。

4.3一般情况下 autoMappingBehavior默认值为PARTIAL,对未明确指定映射规则的字段进行自动映射

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

 由于我们是使用最简单的类型进行查询的,所以我们会把select语句中查询的字段进行自动映射。简单点说就是默认查询的字段 和  表中的字段名是一模一样的,这届根据当前的查询字段进行设置值就ok了。

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

 而值的查询,就是和传统的JDBC代码一样,从ResultSet中获取并设置到目标对象中的:

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

可能有人会说,怎么是把值设置到了metaObject元数据中了呢? 其实,元数据中之前提过了,是会生成BeanWrapper对象的,这就是一个Bean对象。我们最终是通过反射,设置到这个bean对象中的:

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

4.4 映射resultMap中明确指定需要映射的列

这一章节,是我们在xml文件中配置了ResultMap的映射关系,按照映射关系进行设置值的,逻辑与4.3雷同

4.5 如果没有一个映射成功的属性,则根据<returnInstanceForEmptyRow>的配置返回null或者结果对象

这一步就没有什么好说的了, rowValue = foundValues || configuration.isReturnInstanceForEmptyRow() ? rowValue : null;

5. 保存映射结果对象

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

其实,大部分的映射都是放置在 resultHandler  和  resultContext中的。

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

5.1  resultContext 计数作用

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

 5.2 ResultHandler存储结果集

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

也就是说,能够获取到ResultHandler对象,就可以获取到封装好了的所有结果集了。

6. 主流程over

待我们获取到ResultHandler对象以后,就可以从ResultHandler对象中获取到所有的结果集,并放入名称为multipleResults的List中。

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

然后就是一路返回List到Executor组件中;MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

接着返回,因为我们查询调用的是SqlSession中的 selectOne 方法,所有只会返回1条数据。

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

而调用的入口方法在此处:

MyBatis源码分析_ResultSetHandler(7),Mybatis,mybatis,java,servlet

至此,全部调用完毕,返回到我们自己写的业务代码处。 文章来源地址https://www.toymoban.com/news/detail-606884.html

到了这里,关于MyBatis源码分析_ResultSetHandler(7)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MyBatis 源码分析(五):异常模块

    上一篇我们解了Mybatis解析器模块,本篇我们来了解反射模块。本文,我们来分享 MyBatis 的异常模块。 对应  exceptions  包,如下图所示: 在 MyBatis源码分析(二):项目结构 中,简单介绍了这个模块: 定义了 MyBatis 专有的 PersistenceException 和 TooManyResultsException 异常。 实际上

    2024年02月01日
    浏览(30)
  • Mybatis源码分析_日志模块 (1)

    不得不承认,学习MyBatis的时间成本要比学习Spring低很多,Mybatis是我所了解过的代码量最小、整体架构最简单,但是又是最具有学习价值的一个框架。如果,你想快速的阅读一个框架的源码,并且掌握这个框架的精髓,那么Mybatis一定是你的首选。 在开始我们的源码阅读之前,

    2024年02月10日
    浏览(28)
  • MyBatis-Executor源码全面分析

    MyBatis版本-5.1.3 本篇文章主要分析MyBatis中执行器与插件的相关原理与源码。再分析源码之前,需要回顾一下基础的前置知识。 1. JDBC开发回顾 1.1 JDBC代码案例 Java DataBase Connectivity Java 数据库连接, Java语言操作数据库 JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型

    2024年02月12日
    浏览(32)
  • 【Mybatis源码解析】mapper实例化及执行流程源码分析

    基础环境:JDK17、SpringBoot3.0、mysql5.7 储备知识:《【Spring6源码・AOP】AOP源码解析》、《JDBC详细全解》 基于SpringBoot的Mybatis源码解析: 1.如何对mapper实例化bean 在加载BeanDefinition时,会将SqlSessionFactory、SqlSessionTemplate、MapperScannerConfigurer加载到注册表中,以供后续进行实例化。

    2024年02月01日
    浏览(31)
  • mybatis多参数传递报错问题分析+硬核mybatis底层源码分析+@Param注解+图文实战环境分析【4500字详解打通,没有比这更详细的了!】

    ❗操作 mybatis 时报错: org.apache.ibatis.binding.BindingException: Parameter ‘tableName’ not found. Available parameters are [arg1, arg0, param1, param2] Maven MySQL 8.0.30 在本机 MySQL 中执行: 🍀 pom.xml导入依赖 🍀 jdbc.properties 在 resources 目录下新建 jdbc.properties 配置文件。 🍀 mybatis-config.xml 在 resources 目

    2024年02月12日
    浏览(34)
  • Mybatis源码分析_Mapper接口是如何实例化的 (2)

    我们在使用Spring+mybatis的时候,经常都是直接写一个接口和一个对应的 ***Mapper.xml文件,然后业务代码就可以直接注入这个接口了。它是如何做到的呢? 接口: xml    想搞清楚这个问题,那还是要从Mybatis底层源码进行分析的。Mybatis是一个非常优先的框架,它大量的将所谓的

    2024年02月10日
    浏览(33)
  • JavaWeb:servlet+MyBatis+ajax (商品管理系统)

    1、开发环境 IDEA mysql8.0 ajax servlet 2、环境准备 1、创建数据库 2、创建web项目 3、pom.xml文件导入依赖 4、编写mybatis配置文件 5、创建项目结构导入js 6、编写Mybatis工具类 7、编写实体类 3、功能实现 3.1、查询所有 代码实现 1、在mapper包下编写BrandMapper接口,编写查询所有方法 2、在

    2024年01月23日
    浏览(32)
  • 基于Spring注解 + MyBatis + Servlet 实现数据库交换的小小Demo

    配置数据库连接信息 db.properties 配置web.xml 配置logback.xml配置文件 配置applicationContext.xml 里面的bean 配置myBatis核心配置文件mybatis-config.xml 创建实体类对象User 创建LoginServlet响应前端的数据 创建UserService 接口 创建UserMapper接口 创建UserServiceImpl 接口实现类 按照这样的方式进行拼接

    2024年02月02日
    浏览(73)
  • MyBatis 系列:MyBatis 源码环境搭建

    jdk:17 maven:3.9.5 Mybatis:https://github.com/mybatis/mybatis-3.git Mybatis-Parent:https://github.com/mybatis/parent.git 建议使用git的方式拉取代码,后期就不需要执行 git init 导入两个项目 注意 mybatis-parent 必须采用 jdk版本:11-23,maven版本: 3.9.5 否则提示: ERROR] Rule 1: org.apache.maven.enforcer.rules.

    2024年01月25日
    浏览(31)
  • IDEA开发实现Maven+Servlet+Mybatis实现CRUD管理系统-Mapper代理开发

    之前我们写的代码是基本使用方式,它也存在硬编码的问题,如下: 这里调用 selectList() 方法传递的参数是映射配置文件中的 namespace.id值。这样写也不便于后期的维护。如果使用 Mapper 代理方式(如下图)则不存在硬编码问题。 通过上面的描述可以看出 Mapper 代理方式的目的

    2024年02月05日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包