热门框架系列 (二) -- MyBatis执行全流程;

@TOC# 热门框架系列
记录在程序走的每一步___auth:huf


从新的篇章开始;篇章阅读需要先关注; 因为笔者想参与技术文章的评选.;需要一定的粉丝量; 粉丝量达到一定数量.所有文章阅读限制将会全面放开;谢谢大家的支持
首先说明白一个问题;

1:Mybatis 事务使用的是JdbcTransactionFactory 创建的 那么 JdbcTransactionFactory 会创建自己的 DataSource 然后创建自己的connection;

2: Spring 使用的是CcilocalTransactionManager 来创建 自己的connection; 在我们的Spring系列第十七章有写道 Spring Transaction 创建 connection 是如何创建的;

在Mybatis中; 我们在opensession的时候 就会去创建数据库链接; 跟着源码点进去就行;两个connection 是不一样的;这里再次补一张图;
在这里插入图片描述


我们详细分析以下 整个Mybatis 的整个流程:
在这里插入图片描述

openSession开始;
在sqlsession.openSession(); 我们点进去
在这里插入图片描述
我们可以发现 我们可以通过很多种方法获取到SqlSession
他们内部已经帮我们做了一个回车做了一个分类; 实际上 我们关注点 应该是
ExecutorType

Executor_Type

Mybatis 一共有两大类Executor 执行器; 第一类就是cache 内存执行器 还有一类就是普通执行器 Executor
在这里插入图片描述
从上图我们可以得知 普通Executor 分为三种 一种是SimpleExecutor 一种是ResuseExecutor 还有一种是BatchExecutor

  1. SimpleExecutor:每执行一次update或select,就开启一个 Statement对象,用完立刻关闭Statement对象
  2. ReuseExecutor:执行update或select,以sql作为key查找 Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement 对象,而是放置于Map<String, Statement>内,供下一次使用。简言之, 就是重复使用Statement对象。
  3. BatchExecutor:执行update(没有select,JDBC批处理不支持 select),将所有sql都添加到批处理中(addBatch()),等待统一执行 (executeBatch()),它缓存了多个Statement对象,每个Statement对象 都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批 处理相同。

另外一个大类就是cacheExecutor 是缓存执行器:
CacheExecutor其实是封装了普通的Executor,和普通的区别是在查询前先 会查询缓存中是否存在结果,如果存在就使用缓存中的结果,如果不存在还 是使用普通的Executor进行查询,再将查询出来的结果存入缓存。

我们可以通过openSession来确定自己 即将要使用的执行器; 这个在业务当中有很大作用; 现在我们代码使用的就是普通类型的执行器; 这边就不再累赘每个执行器的执行结果;


在这里插入图片描述
我们可以从返回对象得知 我们的Mapper对象 是代理对象; 既然有代理对象 那么 就一个有代理工厂 来生成这个代理对象; 我们由此引出2个对象MapperProxy
MapperProxyFactory;
在这里插入图片描述
在这里插入图片描述
这样就创建出来了代理Mapper; 我们继续往下走;
在这里插入图片描述
我们知道代理对象执行方法; 执行到MapperProxy 的 invoke 方法 源码不难; 我们解读一次;


public class MapperProxy<T> implements InvocationHandler, Serializable {

  private static final long serialVersionUID = -6424540398559729838L;
  private final SqlSession sqlSession;
  private final Class<T> mapperInterface;
  private final Map<Method, MapperMethod> methodCache;
	构造方法 
  public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
    this.sqlSession = sqlSession;
    this.mapperInterface = mapperInterface;
    this.methodCache = methodCache;
  }
	执行主要方法;
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
    判断是否是一个对象; 如果是一个对象 就直接执行他的方法;
   	这个方法实际上就是Mapper的三种方式是有关系的;
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
      } else if (isDefaultMethod(method)) {
        return invokeDefaultMethod(proxy, method, args);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
    最后走到这个地方; 引出一个对象 MapoperMethod 
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  }

  private MapperMethod cachedMapperMethod(Method method) {
    MapperMethod mapperMethod = methodCache.get(method);
    if (mapperMethod == null) {
      mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
      methodCache.put(method, mapperMethod);
    }
    return mapperMethod;
  }

在这里插入图片描述
该对象是sql执行 的一个对象; 该对象带着sql的属性;带着返回值 我们可以从途中可以看出; 最后由mapperMethod.execute 执行
在这里插入图片描述
我们可以看出execute 会根据Type去判断 如果是select 就直接进select
这时候 DefaultSqlSession 就会去执行sql; 我们持续往下深挖;最后我们会到BaseExecutor.在这里插入图片描述
这里就会由模板模式去决定调取哪个 Executor

到此 我们Mybatis的全部流程 就讲解完了。

总结

Mybatis 是一个非常适合新手上手源码的框架 非常的简单;

  • SqlSessionFactoryBuilder解析配置文件,包括属性配置、别名配置、 拦截器配置、环境(数据源和事务管理器)、Mapper配置等;解析完这些 配置后会生成一个Configration对象,这个对象中包含了MyBatis需要的所 有配置,然后会用这个Configration对象创建一个SqlSessionFactory对 象,这个对象中包含了Configration对象;
  • 拿到SqlSessionFactory对象后,会调用SqlSessionFactory的 openSesison方法,这个方法会创建一个Sql执行器(Executor组件中包含 了Transaction对象),这个Sql执行器会代理你配置的拦截器方法。
  • 获得上面的Sql执行器后,会创建一个SqlSession(默认使用 DefaultSqlSession),这个SqlSession中也包含了Configration对象和上面 创建的Executor对象,所以通过SqlSession也能拿到全局配置;
  • 获得SqlSession对象后就能执行各种CRUD方法了

以上是获得SqlSession的流程,下面总结下本博客中介绍的Sql的执行流程:
  • 调用SqlSession的getMapper方法,获得Mapper接口的动态代理对 象MapperProxy,调用Mapper接口的所有方法都会调用到MapperProxy 的invoke方法(动态代理机制);
  • MapperProxy的invoke方法中唯一做的就是创建一个 MapperMethod对象,然后调用这个对象的execute方法,sqlSession会 作为execute方法的入参;
  • 往下,层层调下来会进入Executor组件(如果配置插件会对Executor 进行动态代理)的query方法,这个方法中会创建一个StatementHandler 对象,这个对象中同时会封装ParameterHandler和ResultSetHandler对 象。调用StatementHandler预编译参数以及设置参数值,使用 ParameterHandler来给sql设置参数

Executor组件有两个直接实现类,分别是BaseExecutor和 CachingExecutor。CachingExecutor静态代理了BaseExecutor。Executor 组件封装了Transction组件,Transction组件中又分装了Datasource组件。
  • 调用StatementHandler的增删改查方法获得结果,ResultSetHandler 对结果进行封装转换,请求结束。
    Executor、StatementHandler 、ParameterHandler、 ResultSetHandler,Mybatis的插件会对上面的四个组件进行动态代理。

  • MapperRegistry:本质上是一个Map,其中的key是Mapper接口的 全限定名,value的MapperProxyFactory;

  • MapperProxyFactory:这个类是MapperRegistry中存的value值, 在通过sqlSession获取Mapper时,其实先获取到的是这个工厂,然后通过 这个工厂创建Mapper的动态代理类;

  • MapperProxy:实现了InvocationHandler接口,Mapper的动态代理 接口方法的调用都会到达这个类的invoke方法;

  • MapperMethod:判断你当前执行的方式是增删改查哪一种,并通过 SqlSession执行相应的操作;

  • SqlSession:作为MyBatis工作的主要顶层API,表示和数据库交互的 会话,完成必要数据库增删改查功能;

  • Executor:MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的 生成和查询缓存的维护;

  • StatementHandler:封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合。

  • ParameterHandler:负责对用户传递的参数转换成JDBC Statement 所需要 的参数

  • ResultSetHandler:负责将JDBC返回的ResultSet结果集对象转换成List类型 的集合;

  • TypeHandler:负责java数据类型和jdbc数据类型之间的映射和转换

  • MappedStatement:MappedStatement维护了一条 <select|update|delete|insert>节点的封装

  • SqlSource:负责根据用户传递的parameterObject,动态地生成SQL语句, 将信息封装到BoundSql对象中,并返回

  • BoundSql:表示动态生成的SQL语句以及相应的参数信息

  • Configuration:MyBatis所有的配置信息都维持在Configuration对象之中。

seeyou

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Like Java Long Time

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值