Mybatis的SqlSession执行sql过程
上一篇分析了SqlSession的创建过程,接下来就来到最后一步执行sql的过程了。
执行sql总览
首先还是来看下目前分析的代码所处的位置,具体的代码如下:
之前也说过要使用mybatis操作数据库,在代码里面与mybatis相关的代码只需要三步:创建SqlSessionFactory对象,利用SqlSessionFactory对象创建SqlSession,最后利用SqlSession执行sql。到目前为止已经分析到最后一步,接下来详细分析sql是如果得到并执行的。
SqlSession执行部分
上图可以看到即使调用的selectOne方法还是依赖的是selectList方法,然后根据查询结果的数量来判断,如果超过一条则直接抛出异常。我通过在sql中加1=1 or测试确实是能够查出所有的数据然后报错。
这里实际上是我觉得不太好的实现,如果程序员不小心写错了sql在某种情况下可以查出多条甚至是全表,可能在测试环境没有测出来,而在线上环境出现,那么将是对数据库和程序都是灾难,当然这种情况出现的可能性特别小。而mybatis没有考虑这种情况不知道是不是因为是我理解不到位。
接下来看DefaultSqlSession的selectList方法,DefaultSqlSession重载了三个selectList方法,最终都会调用参数最全的那个方法。这个方法只有两个关键步奏:首先通过参数statement从全局配置configuration获取到对应的MappedStatement对象,然后使用得到的对象和参数parameter调用executor的query方法。其中参数statement就是最开始传递的参数“com.itlezhi.mybatis.mapper.MemberMapper.getById”,parameter对应参数5。
通过这个方法应该能够彻底清楚全局配置configuration的属性Map<String, MappedStatement> mappedStatements中key对应的是什么东西了。
executor的query方法
执行器executor上一篇文章有分析,默认是SimpleExecutor这个类,其中包含有全局配置configuration和事务Transaction,而事务Transaction中有从configuration中得到的DataSource,而DataSource中包含有数据库的连接信息。他封装了一些数据库查询。不过上面说到的query方法属于基础方法,在BaseExecutor类中代码如下图:
最终还是来到SimpleExecutor这个类中,具体代码如下图:
里面的代码还是比较简单的,旁边我还写了一个直接使用jdbc查询的demo进行比较,可以看到主流程已经差不多一致,不同的点在于获取connection和对结果的处理。
获取connection是通过BaseExecutor的getConnection方法实现,实际上是调用的属性transaction实现,而transaction是通过属性dataSource来实现,这些都在上一篇文章中。
另外一个不同点就是对结果的封装,这个后面细说,这两个不同点也是使用mybatis的优势之一。
总结
今天分析的sql执行过程可以说是只从宏观上面进行了分析,具体的实现细节并没有仔细分析,比如sql是如何得到的,参数如何设置的,结果又是如何封装了,可以说这些细节才是真正mybatis对应jdbc的优势所在。不过先分梳理清楚了主流程,接下来再来分析具体的流程。
Java程序员日常学习笔记,如理解有误欢迎各位交流讨论!