Mybatis 作为国内开发中常用到的半自动 orm 框架,相信大家都很熟悉,它提供了简单灵活的xml映射配置,方便开发人员编写简单、复杂SQL,在国内互联网公司使用众多。
本文针对笔者日常开发中对 Mybatis
返回类型的是否需要判断为 null
结合源码,思考总结而来
Mybatis
版本 3.5.11Spring boot
版本 3.0.1- github地址:https://github.com/wayn111, 欢迎大家关注,点个star
一. 流程图分析
直接给出博主梳理的调用流程图,从用户dao方法执行开始,经过 Mybatis
动态代理,对返回结果进行处理再到到结束
其中有几个比较重要的类,我说明一下
MapperMethod
对SQL执行类型进行判断,判断是insert、update、delete还是select类型,每个类型的处理流程都不一样PrepareStatementHandler
对完成参数替换后的SQL语句执行数据库查询,返回ResultSetDefaultResultHandler
对执行结果进行处理转换
二. DefaultResultSetHandler对返回结果进行处理
在 Mybatis
中 ResultSetHandler
接口用于在 StatementHandler
对象执行完查询操作或存储过程后,对结果集或存储过程的执行结果进行处理。同理,当返回集合类型时,Mybatis
最后也会交给 ResultSetHandler
的实现类 DefaultResultSetHandler
来处理,最终在 handleResultSet()
方法中完成对返回集合类型的处理,如下图
可以看出,Mybatis
先创建 DefaultResultHandler
对象,接着放入 handleRowValues()
方法中,该方法会把数据库查询返回的多条记录转换为 resultMap
对应的对象放入 defaultResultHandler
,最后调用 defaultResultHandler.getResultList()
方法将结果放到最终返回需要的 multipleResults
中。multipleResults
对象中就包含了我们最终返回的集合对象
三. DefaultResultHandler一个包含实际要返回集合对象的处理类
在上面代码中有一个非常重要的类,那就是 DefaultResultHandler
类,实际上我们返回的集合对象就是 DefaultResultHandler
内部的成员属性 list
,查看源码
- 里面有一个
list
成员属性,该属性在构造器中由objectFactory
对象调用create(List.class)
方法创建,进入其中
在 resolveInterface(type)
方法中,对传入的类对象做具体转换
可以看到 List.class
被转换为 ArrayList.class
,接着调用 instantiateClass()
方法,完成空集合的创建,(划重点)由此可见,Mybatis
返回集合类型默认是空集合
-
handlerResult(ResultContext<?> context)
方法,该方法会往list
中添加元素 -
getResultList()
方法,直接返回list成员属性
结合上面提到的最后调用 defaultResultHandler.getResultList()
方法将结果放到最终返回需要的 multipleResults
中,我们很容易就能知道,我们返回的集合对象实际上就是 DefaultResultHandler
类中的 list
属性,然后我们重新梳理下上文提到的 handleResultSet()
方法
- 先创建
DefaultResultHandler
对象,初始化list
成员属性为空集合 - 在
handleRowValues()
方法中,处理返回记录,转换为resultMap
对应的对象类型,这个过程中,如果数据库返回不为空,就会调用DefaultResultHandler
类中的handlerResult(ResultContext<?> context)
方法,将返回对象放入成员属性list
集合中 - 调用
defaultResultHandler.getResultList()
方法,将成员属性list
集合放入multipleResults
中,这也就对应了上文提到的multipleResults
对象中就包含了我们最终返回的集合对象
四. 总结
由上经过源码分析,我们知道 Mybatis
返回集合类型默认是空集合,我们在日常开发中,对于 Mybatis
返回集合类型不需要判断是否为 null
,直接调用 list.size() > 0
或者其他第三方工具包提供的集合判空方法即可