【mybatis源码分析(三)】mybatis sqlSession执行的过程

一、先认识一些关键接口和类

(1)Mybatis四大核心组件

  1. Executor:它作用于创建缓存,管理StatementHander的调用,为StatementHandler提供Configuration环境。
  2. StatementHander:它主要用于创建statement对象于数据库进行交互。
  3. ParamenterHandler:它主要用于在PreparedStatement对象的预编译sql的参数配置
  4. ResultSetHandler:它主要用于把查询结果和实体类进行绑定

1、Executor 接口(执行器用来执行sql语句

主要包含四种实现类:

  • SimpleExecutor :简单执行器,所有数据库操作委托给StatementHandler处理
  • ReuseExecutor:复用执行器,与SimpleExecutor类似,只是根据sql缓存了JDBC的statement,遇到相同sql省去了statement的创建,需要手动执行flushStatement清除缓存。
  • BatchExecutor:批量执行器,使用JDBC的batchUpdate方法,需要手动执行SqlSession的flushStatements立即执行sql。
  • CachingExecutor:缓存执行器

2、StatementHandler接口(用于处理JDBC中的Statement接口

  • SimpleStatementHandler:对应JDBC中的Statement接口,用于简单sql的处理。
  • PreparedStatementHandler:对应JDBC中的PreparedStatement预编译sql的接口。
  • CallableStatementHandler:对应JDBC中的CallableStatement接口,用于执行存储过程相关的接口。
  • RoutingStatemengtHandler:对以上三个接口的路由,只是负责创建和调用。

3、ParameterHandler接口(参数处理器,为PreparedStatement的sql语句参数动态赋值

参数解释:

  • getParameterObject: 用于读取参数
  • setParameters: 用于对 PreparedStatement 的参数赋值

4、ResultSetHandler接口(用于结果集的处理,按照Mapper文件中的ResultType和ResultMap来封装成对应的对象并返回。

只有DefaultResultSetHandler一个实现类

  • handleResultSets:将statement执行后产生的结果集(多个结果集)映射为结果列表
  • handleCursorResultSets:处理游标结果集
  • handleOutputParameters :处理存储过程执行后的输出参数

(2)其他关键接口和类

1、Configuration类:是整个mybatis核心配置类,所有的xml等信息,最终都会解析到Configuration类

2、MappedStatement类:用于存mapper文件中的mapper标签信息。

3、ResultMap类:用于存放mapper文件中resultMap标签信息

4、ResultMapping类:存放mapper文件中resultMap标签中result信息,用作java和mysql的列映射类

5、boundSql类:用于处理动态sql后,返回sql字符串

6、ResultSetWrapper类:用于对ResultSet结果集的包装类

7、ResultHandler接口:用于自定义处理返回结果,使用sqlSessionTemplate的select方法实现,用于流式查询,防止大数据导致oom。


8、ResultContext接口:唯一实现类是DefaultResultContext。是ResultHandler接口的参数,每个ResultContext代表一条数据,可以通过getResultObject获取到数据。

9、TypeHandler接口:类型处理器。用于处理javaType和JdbcType之间的转换,还用于PreparedStatement设置参数值和从ResultSet或CallableStatement中取出值。

10、RowBounds类:用于mybatis逻辑分页,原理是取出所有数据,舍弃前面offset条数据,取剩下数据的limit条。性能不好。推荐使用PageHelper分页插件,底层是通过拦截器添加limit语句。


二、SqlSession执行的过程

无论我们使用Mapper的形式执行sql,还是sqlSessionTemplate的方式,最终都会执行到DefaultSqlSession的selectList方法(列表查询)

前面请参考:https://blog.csdn.net/sumengnan/article/details/113953507,这里就直接从selectList方法开始了。

1、DefaultSqlSession的selectList方法

从configuration中获取MappedStatement信息(可以获取到,因为项目启动时,所有mapper.xml文件中的内容都已经解析到configuration中了)

executor的类型是根据项目启动时的配置生成的,默认是Simple,如果开启缓存则是cachingExecutor

2、query方法是SimpleExecutor的抽象类BaseExecutor的方法用于查询

如果缓存中存在,则走handleLocallyCachedOutputParameters,否则走queryFromDatabase从数据库去查询数据。

3、BaseExecutor的queryFromDatabase方法用于查询

主要用于缓存些数据,之后调用doQuery方法

4、这个doQuery方法,才是真正让子类去实现的方法

4.1构建statementHandler

可以看到使用了RoutingStatementHandler算是静态代理类吧

之后又加入插件拦截器,用于拦截之后自定义处理,例如:PageHepler分页插件

4.2、开始准备Statement对象

从transaction中获取Connection数据库连接(这不就是JDBC的第一步吗?先获取数据库连接

初始化statement:从connection中创建Statement对象(这不就是JDBC的第二步吗?创建Statement对象

如果是Executor是PreparedExecutor的话,会获取prepareStatement对象,并且会执行handler.parameterize(stmt)方法。

去设置参数,如果是String类型的将执行StringTypeHandler类使用ps.setString(i, parameter);设置参数值(这不就是JDBC的第三步吗?预编译SQL参数赋值

5、回到第4步的doQuery方法,继续执行handler.query方法

执行了statement.execute(sql);去执行sql查询。(这不就是JDBC的第四步吗?执行execute方法执行sql查询

6、继续进入handleResultSets方法

结果集ResultSet可能有多个

6.1、进入getFirstResultSet获取结果集这不就是JDBC的第五步吗?获取ResultSet结果集

然后把结果包装进了ResultSetWrapper类中

7、进入HandleResultSet方法去处理结果集

如果你没有自定义ResultHandler处理结果集类,那么默认使用DefaultResultHandler去处理结果集

8、进入HandlerRowValues方法,处理每一行数据

handleRowValuesForSimpleResultMap为简单结果映射

handleRowValuesForNestedResultMap为嵌套结果映射(多表查询)。

9、进入简单结果映射

10、把处理的结果放在DefaultResultHandler的List集合中,返回

猜你喜欢

转载自blog.csdn.net/sumengnan/article/details/114186961