天天看点

Mybatis返回集合类型到底是空集合还是null?源码解读

作者:java小悠
Mybatis 作为国内开发中常用到的半自动 orm 框架,相信大家都很熟悉,它提供了简单灵活的xml映射配置,方便开发人员编写简单、复杂SQL,在国内互联网公司使用众多。

本文针对笔者日常开发中对 Mybatis 返回集合类型是否需要判断为 null 结合源码,思考总结而来

  • Mybatis 版本 3.5.11
  • Spring boot 版本 3.0.1
  • github地址:github.com/wayn111

一. 流程图分析

直接给出博主梳理的调用流程图,从用户dao方法执行开始,经过 MapperProxy 动态代理,对返回结果进行处理再到结束

Mybatis返回集合类型到底是空集合还是null?源码解读

其中有几个比较重要的类,我说明一下

  • MapperMethod 对SQL执行类型进行判断,判断是insert、update、delete还是select类型,每个类型的处理流程都不一样
  • PrepareStatementHandler 对完成参数替换后的SQL语句执行数据库查询,返回ResultSet
  • DefaultResultHandler 对执行结果进行处理转换

二. DefaultResultSetHandler对返回结果进行处理

在 Mybatis 中 ResultSetHandler 接口用于在 StatementHandler 对象执行完查询操作或存储过程后,对结果集或存储过程的执行结果进行处理。同理,当返回集合类型时,Mybatis 最后也会交给 ResultSetHandler 的实现类 DefaultResultSetHandler 来处理,最终在 handleResultSet() 方法中完成对返回集合类型的处理,如下图

Mybatis返回集合类型到底是空集合还是null?源码解读

可以看出 Mybatis 先创建 DefaultResultHandler 对象,接着放入 handleRowValues() 方法中,该方法会把数据库查询返回的多条记录转换为 resultMap 对应的对象放入 defaultResultHandler,最后调用 defaultResultHandler.getResultList() 方法将结果放到最终返回需要的 multipleResults 中。multipleResults 对象中就包含了我们最终返回的集合对象,Mybatis 会从 multipleResults 中获取第一个元素作为 MapperProxy 的返回结果

三. DefaultResultHandler一个包含实际要返回集合对象的处理类

在上面代码中有一个非常重要的类,那就是 DefaultResultHandler 类,实际上我们返回的集合对象就是 DefaultResultHandler 内部的成员属性 list ,查看源码

Mybatis返回集合类型到底是空集合还是null?源码解读
  • 里面有一个 list 成员属性,该属性在构造器中由objectFactory对象调用 create(List.class) 方法创建,进入其中
Mybatis返回集合类型到底是空集合还是null?源码解读

在 resolveInterface(type) 方法中,对传入的类对象做具体转换

Mybatis返回集合类型到底是空集合还是null?源码解读

可以看到 List.class 被转换为 ArrayList.class,接着调用 instantiateClass() 方法,完成空集合的创建,(划重点)由此可见,Mybatis 返回集合类型默认是空集合

  • handlerResult(ResultContext<?> context) 方法,该方法会往 list 中添加元素
  • getResultList() 方法,直接返回list成员属性

结合上面提到的最后调用 defaultResultHandler.getResultList() 方法将结果放到最终返回需要的 multipleResults 中,我们很容易就能知道,我们返回的集合对象实际上就是 DefaultResultHandler 类中的 list 属性,然后我们重新梳理下上文中第二部分:

DefaultResultSetHandler对返回结果进行处理

  1. 先创建 DefaultResultHandler 对象,初始化 list 成员属性为空集合
  2. 在 handleRowValues() 方法中,处理返回记录,转换为 resultMap 对应的对象类型,这个过程中,如果数据库返回不为空,就会调用 DefaultResultHandler 类中的 handlerResult(ResultContext<?> context) 方法,将返回对象放入成员属性 list 集合中
  3. 调用 defaultResultHandler.getResultList() 方法,将成员属性 list 集合放入multipleResults 中,这也就对应了上文提到的 multipleResults 对象中就包含了我们最终返回的集合对象

四. 总结

由上经过源码分析,我们知道 Mybatis 返回集合类型默认是空集合,我们在日常开发中,对于 Mybatis 返回集合类型不需要判断是否为 null,直接调用 list.size() > 0 或者其他第三方工具包提供的集合判空方法即可

原文链接:https://juejin.cn/post/7188878848228851769

继续阅读