前面的获取对象的过程基本都debug完了,下面看最后一行:
String name = mapper.selectNameById(1);
也就是执行SQL语句的具体过程。
下面从SQL语句的执行开始debug:
1、String name = mapper.selectNameById(1);
我们自定义的接口UserMapper是个接口,没有实现类,前面分析获取mapper时我们知道,mybatis会为mapper类生成代理类,生成代理类的方法是使用MapperProxyFactory工厂类生成,代理的类其实就是MapperProxy,所以我们要看下一步的执行过程就要进入这个类进行查看,
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
其中第一个if判断 if (Object.class.equals(method.getDeclaringClass())) ,这个MapperProxy就是一个InvocationHandler(他的作用是jdk创建动态代理时用的,没印象的可以复习一下),也就是我们会根据当前的接口创建一个这个接口的动态代理对象,使用动态代理对象再利用反射调用实际对象的目标方法。
然而动态代理对象里面的方法都是Interface规定的。但是动态代理对象也能调用比如toString(),hashCode()等这些方法呀,这些方法是所有类从Object继承过来的。
所以这个判断的根本作用就是,如果利用动态代理对象调用的是toString,hashCode,getClass等这些从Object类继承过来的方法,就直接反射调用。如果调用的是接口规定的方法。我们就用MapperMethod来执行。所以这个判断是十分必要的。
继续看下面的方法,判断出不是Object的方法,是接口的方法,所以执行下面的代码,从cachedMapperMethod中获取要执行的方法:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
这是个典型的从缓存中获取方法对象的代码,如果缓存中没有,就新建并加入缓存,最后返回这个方法,methodCache对象是一个map,存储了创建过的方法对象,创建的方式是根据接口,方法和配置对象进行创建。到这里我们就获取了我们实际要执行的方法的对象了。
现在我们回来继续看第二步,回到org.apache.ibatis.binding.MapperProxy#invoke方法中,
最后一行代码return中执行的,就是真正操作数据库的方法。我们继续看下一步:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
进入这个方法可以看到,内容很丰富,开始是一个判断语句块,判断当前的操作是什么类型,我们通过idea来看一下正在执行的是什么类型:
如果是增删改的话,执行方式比较一致和简单,
准备好参数然后去执行,本次执行的是查询操作,所以我们主要看下面的SELECT:
查询操作通过判断返回的类型,执行对应的方法,前面几种是比较经典的返回类型,如果都不满足,就会执行else内的方法,本次的selectNameById方法执行的就是else中的内容:
第一行是转换参数为SQL命令中的形式,下面这一行是关键,真正执行的是sqlSession.selectOne方法,我们在前面讨论获取sqlSession对象的源码的时候,查看了SqlSession类中的方法,这是其中一个。传入的第一个参数就是方法:
第二个就是参数,下面我进入这个方法,查看流程:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
我们在使用mybatis的时候,用的是官方文档建议的方法,获取mapper对象,使用mapper对象执行我们自定义的数据库操作方法。官方文档上还有另一种调用方法:
就是直接调用sqlSession中的方法,上面图片例子中的两个参数就是我们前面的过程在组合的参数,也就是说获取mapper对象执行方法最终的过程也是执行sqlSession中的内容,和上面这种方法殊途同归。我们继续来看selectOne中的内容,selectOne最终的执行过程也是执行selectList查询一个列表,然后获取列表中的第一个元素,继续看selectList方法:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
这里加了一个方法参数,RowBounds.DEFAULT,这是物理分页传入的默认参数,返回的结果其实分页了,但是和没分页效果一样,下面继续调用:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
我们在执行jdbc的时候,先编译SQL语句,获取一个Statement对象,这里获取的是一个MappedStatement对象,这个类对应的就是select标签。类的属性和select标签的属性一致。下面这一行executor.query方法执行操作,继续看下面的代码,使用Executor的对象执行,Executor是一个接口,有两个实现类,通过工具可以看到这里使用的是CachingExecutor类的对象实例执行的:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
通过类名我们可以猜测到,这个Executor执行类是使用内存的,将数据保存到缓存中,这样可以有效的解决增删改查性能。缓存的作用域为mapper(namespace),所以同一个namespace的操作会影响到相同作用域下的缓存,这样不同的域对同一个表进行操作很有可能导致缓存中的数据不一样,出现问题,还是不推荐使用。我们看方法的内容:
前面两行是创建缓存值,获取记录,继续往下看:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
上面这个过程就是一级缓存的内容,如果缓存里不为空,就从缓存中查询,如果缓存为空,就查询数据库,这里启动程序只进行一次查询,所以会走查询数据库的分支,最后一行的delegate对象,也是一个Executor对象,这里走不使用缓存的分支,执行操作使用的BaseExecutor对象:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
这里从数据库查,走的是:
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
这条代码分支,从名字可以看出从数据库查询,参数中传了很多,除了编译好的SQL,还有分页,结果的handler,等等,这些是mybatis封装jdbc后以自己的特色去执行SQL的方式,这种麻烦的方法简化了我们使用mybatis的方式,下面继续看:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
看代码:
localCache.putObject(key, EXECUTION_PLACEHOLDER);
这里查询了一次以后,加入了一级缓存当中,下面就是执行doQuery方法:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
12、org.apache.ibatis.executor.SimpleExecutor#doQuery
这里进入了SimpleExecutor类中,第一行的Statement stmt =null;代码有点眼熟,就是我们jdbc中的Statement 对象,说明我们马上要接近真相了!继续,前面三个是对SQL语句进行预编译,然后执行query方法,通过debug,知道下一步执行这个方法:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
12、org.apache.ibatis.executor.SimpleExecutor#doQuery
13、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
这里就是一行调用,继续debug:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
12、org.apache.ibatis.executor.SimpleExecutor#doQuery
13、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
第一行是jdk中jdbc的类,执行获取预编译操作,然后执行了ps.execute();,这个就是我们的jdbc方法!终于到这里了!resultSetHandler是mybatis的对象,包装jdbc的结果,我们继续看:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
12、org.apache.ibatis.executor.SimpleExecutor#doQuery
13、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
15、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets
ResultSetHandler负责处理两件事,一是处理Statement执行后产生的结果集,生成结果列表,二是处理存储过程执行后的输出参数。DefaultResultSetHandler类是ResultSetHandler的默认实现,这里执行了这个类的handleResultSets方法,其实现的步骤就是将Statement执行后的结果集,按照Mapper文件中配置的ResultType或ResultMap来封装成对应的对象,最后将封装的对象返回即可,这里有一行代码:
ResultSetWrapper rsw = getFirstResultSet(stmt);
我们进入getFirstResultSet方法看一看:
这里的代码很眼熟了,就是jdbc接收结果的过程,最后一行把这个结果封装成了mybatis中的结果对象,封装的过程如下:
这里面包含的记过的很多熟悉,类型,名称,对象的类型,等等。我们继续来看handleResultSets方法,组合好多个返回结果的list后,我们看最后一行代码,执行collapseSingleResultList方法:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
12、org.apache.ibatis.executor.SimpleExecutor#doQuery
13、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
15、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets
16、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList
从判断可以看出,在判断是不是只有一条结果,这样封装返回结果的对象就执行完了。我们再次返回前面的方法:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
12、org.apache.ibatis.executor.SimpleExecutor#doQuery
13、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
15、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets
16、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList
17、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
这里是前面的方法,返回的就是符合类型的结果的list,无论一条还是多条,继续debug:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
12、org.apache.ibatis.executor.SimpleExecutor#doQuery
13、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
15、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets
16、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList
17、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
18、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
继续往回执行:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
12、org.apache.ibatis.executor.SimpleExecutor#doQuery
13、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
15、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets
16、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList
17、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
18、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
19、org.apache.ibatis.executor.SimpleExecutor#doQuery
继续往回执行:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
12、org.apache.ibatis.executor.SimpleExecutor#doQuery
13、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
15、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets
16、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList
17、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
18、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
19、org.apache.ibatis.executor.SimpleExecutor#doQuery
20、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
这里把最终的查询结果放到了一级缓存中,然后继续往回执行:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
12、org.apache.ibatis.executor.SimpleExecutor#doQuery
13、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
15、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets
16、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList
17、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
18、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
19、org.apache.ibatis.executor.SimpleExecutor#doQuery
20、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
21、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
这里面对缓存最后进行处理,继续往回看:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
12、org.apache.ibatis.executor.SimpleExecutor#doQuery
13、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
15、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets
16、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList
17、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
18、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
19、org.apache.ibatis.executor.SimpleExecutor#doQuery
20、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
21、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
22、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
23、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
24、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
25、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
26、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
最后带着list回到了selectOne这里,
查询成功以后,返回了第一个对象,下面是代理对象:
1、String name = mapper.selectNameById(1);
2、org.apache.ibatis.binding.MapperProxy#invoke
3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod
4、org.apache.ibatis.binding.MapperMethod#execute
5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
12、org.apache.ibatis.executor.SimpleExecutor#doQuery
13、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
15、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets
16、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList
17、org.apache.ibatis.executor.statement.PreparedStatementHandler#query
18、org.apache.ibatis.executor.statement.RoutingStatementHandler#query
19、org.apache.ibatis.executor.SimpleExecutor#doQuery
20、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase
21、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
22、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)
23、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)
24、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)
25、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)
26、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)
27、org.apache.ibatis.binding.MapperMethod#execute
28、org.apache.ibatis.binding.MapperProxy#invoke
29、String name = mapper.selectNameById(1);
最终我们回到了调用的地方,返回了查询的name!
总结
来总结一下,通过debug看源码是一个不太会看源码的人的一个不错的方法,我们上面通过debug来查看了mybatis查询的整个过程,中间的一级缓存,涉及到的几种查询Executor,获取返回结果的ResultSetHandler,编译的StatementHandler,物理分页的RowBounds等等几个对象是如果对jdbc查询的整个过程进行润色的,查询的整个过程在这个源码分析中是最复杂的,正是由于这个复杂,我们才能轻松的使用mybatis!