执行增删改查方法
进入invoke方法,调用execute方法。
execute()方法中根据SQL类型,是insert还是select,在走对应的逻辑。因为当前我这个是select,我直接截了select中的代码。第一步就是封装参数,之前参数那节课讲过的。然后进行查询。
进入查询方法,调用的selectList方法。
在Configuration中通过statement(全类名)获取MappedStatement对象。这个对象里面包括了该sql-select标签的全部信息。最后会在executor中进行sql调用。this.wrapCollection(parameter)这个方法也是参数封装。
进入query方法,首先获取BoundSql对象。其实就是有sql的相关详细信息包括sql,参数等。因为咱们全局配置中开启了二级缓存。所以会有这个CacheKey。各种参数组装的key。再进入query方法。
可以看出,即使我们使用了CacheExecutor,其实最后用的还是SimpleExecutor。CacheExecutor只不过是一个包装。从这个会查询二级缓存,没有二级缓存直接调用SimpleExecutor的query方法进行查询。
从query方法中可以看出,mybatis先查询的是二级缓存,没有数据就会查询一级缓存。再没有就会查询数据库。进入queryFromDatabase,查看mybatis是如何查询的。
从数据库查询完后,会再将数据放入本地缓存中,也就是一级缓存。所以说一级缓存是一直有的。这在之前的缓存机制的学习笔记中所说的是完全符合的。我们再看doQuery方法是这么实现的?方法中的参数我们都很熟悉,MappedStatement是存放该select标签的所有信息,parameter是查询参数,rowBounds是分页用的,resultHandler是返回值使用的,boundSql是含有sql相关信息
第一步声明了一个Statement,这个Statement就是原生jdbc的。会发现有四大对象之一StatementHandler,可以创建Statement对象。进入newStatementHandler方法,进入RoutingStatementHandler方法。最终其实返回的是prepareStatement。然后通prepareStatement方法,里面就是sql和参数预编译封装到Statement中。通过handler.query()获取查询结果。
在这里我们又发现了this.interceptorChain.pluginAll(statementHandler); 这个在Executor创建的时候也有这个。使用拦截器进行包装返回。
首先会获取StatementType这个是select标签中的的一个属性值。默认prepare。它又会创建一个PreparedStatementHandler。
handler.parameterize(stmt);就是参数预编译。进入该方法,parameterHandler又是一个四大对象之一。通过它来设置参数。其实在创建StatementHandler对象时,就已经创建了parameterHandler,resultSetHandler。再进入这两个对象的创建方法, 也是通过拦截器this.interceptorChain.pluginAll(resultSetHandler)创建。
回到话题中,上面说到参数预编译:进入setParameter方法中,会看见TypeHandler 类型处理器。调用他的setParameters方法,将传过来的PrepareStatement中sql预编译设置参数。
最后通过handler.query获取查询结果,进入query方法中,最后将处理结果使用resultHandler进行封装。
最后也是resultHandler中也是使用TypeHandler对结果数据封装。
增删改查执行流程图
总结
/**
* 首先通过inputStream读取mybatis全局配置文件,通过sqlSessionFactoryBuilder的build方法
* 创建sqlSessionFactory对象
*
* 1、获取sqlSessionFactory对象:
* build中的方法就是,xmlConfigBuilder解析inputStream中的参数,解析文件的每一个信息保存在Configuration中,返回包含Configuration的DefaultSqlSession;
* 注意:【MappedStatement】:代表一个增删改查的详细信息
* <p>
* 2、获取sqlSession对象
* 返回一个DefaultSQlSession对象,包含Executor和Configuration;
* 这一步会创建Executor对象;
* <p>
* 3、获取接口的代理对象(MapperProxy)
* getMapper,使用MapperProxyFactory创建一个MapperProxy的代理对象
* 代理对象里面包含了,DefaultSqlSession(Executor)
* 4、执行增删改查方法
* <p>
* 总结:
* 1、根据配置文件(全局,sql映射)初始化出Configuration对象
* 2、创建一个DefaultSqlSession对象,
* 他里面包含Configuration以及
* Executor(根据全局配置文件中的defaultExecutorType创建出对应的Executor)
* 3、DefaultSqlSession.getMapper():拿到Mapper接口对应的MapperProxy;
* 4、MapperProxy里面有(DefaultSqlSession);
* 5、执行增删改查方法:
* 1)、调用DefaultSqlSession的增删改查(Executor);
* 2)、会创建一个StatementHandler对象。
* (同时也会创建出ParameterHandler和ResultSetHandler)
* 3)、调用StatementHandler预编译参数以及设置参数值;
* 使用ParameterHandler来给sql设置参数
* 4)、调用StatementHandler的增删改查方法;
* 5)、ResultSetHandler封装结果
* 注意:
* 四大对象每个创建的时候都有一个interceptorChain.pluginAll(parameterHandler);
*
*/