面试:谈谈你对MyBatis执行过程之SQL执行过程理解

本文详细介绍了MyBatis的SQL执行过程,从SqlSession的创建到MapperProxy的使用,再到Executor、StatementHandler、ParameterHandler和ResultSetHandler的执行流程,深入理解MyBatis的执行机制,有助于开发和面试中问题的定位。
摘要由CSDN通过智能技术生成

面试:谈谈你对MyBatis执行过程之SQL执行过程理解

 

前言

在了解了MyBatis初始化加载过程后,我们也应该研究看看SQL执行过程是怎样执行?这样我们对于Mybatis的整个执行流程都熟悉了,在开发遇到问题也可以很快定位到问题。

更重要的,在面试中遇到面试官咨询Mybatis的知识点的时候,可以很顺畅的把这一套流程讲出来,面试也会觉得你已掌握Mybatis知识点了。

SQL执行过程简介

经过MyBatis初始化加载Sql执行过程所需的信息后,我们就可以通过 SqlSessionFactory 对象得倒忙SqlSession ,然后执行 SQL 语句了,接下来看看Sql执行具体过程,SQL大致执行流程图如下所示:

面试:谈谈你对MyBatis执行过程之SQL执行过程理解

 

接下来我们来看看每个执行链路中的具体执行过程,

SqlSession

SqlSession 是 MyBatis 暴露给外部使用的统一接口层,通过 SqlSessionFactory 创建,且其包含和数据库打交道所有操作接口。

下面通过时序图描述 SqlSession 对象的创建流程:

面试:谈谈你对MyBatis执行过程之SQL执行过程理解

 

在生成 SqlSession 的同时,基于 executorType 初始化好 Executor 实现类。

public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
   executorType = executorType == null ? defaultExecutorType : executorType;
   executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
   Executor executor;   if (ExecutorType.BATCH == executorType) {
     executor = new BatchExecutor(this, transaction);
  } else if (ExecutorType.REUSE == executorType) {
     executor = new ReuseExecutor(this, transaction);
  } else {
     executor = new SimpleExecutor(this, transaction);
  }   if (cacheEnabled) {
     executor = new CachingExecutor(executor);
  }   executor = (Executor) interceptorChain.pluginAll(executor);   return executor;
}

最顶层的SqlSession接口已生成,那我们可以来看看sql的执行过程下一步是怎样的呢? 怎样使用代理类 MapperProxy 。

MapperProxy

MapperProxy 是 Mapper 接口与SQL 语句映射的关键,通过 MapperProxy 可以让对应的 SQL 语句跟接口进行绑定的,具体流程如下:

  • MapperProxy 代理类生成流程
  • MapperProxy 代理类执行操作

MapperProxy 代理类生成流程

面试:谈谈你对MyBatis执行过程之SQL执行过程理解

 

其中, MapperRegistry 是 Configuration 的一个属性,在解析配置时候会在 MapperRegistry 中缓存了 MapperProxyFactory 的 knownMappers 变量 Map 集合。

MapperRegistry 会根据 mapper 接口类型获取已缓存的 MapperProxyFactory , MapperProxyFactory 会基于 SqlSession 来生成 MapperProxy 代理对象,

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
       MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
       if (mapperProxyFactory == null) {
           throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
      } else {
           try {
               return mapperProxyFactory.newInstance(sqlSession);
          } catch (Exception var5) {
               throw new BindingException("Error getting mapper instance. Cause: " + var5, var5);
          }      }  }

当调用 SqlSession 接口时, MapperProxy 怎么是实现的呢? MyBatis 的 Mapper 接口 是通过动态代理实现的,调用 Mapper 接口的任何方法都会执行 MapperProxy::invoke() 方法,

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       try {
           //Object类型执行
           if (Object.class.equals(method.getDeclaringClass())) {
               return method.invoke(this, args);
          }
//接口默认方法执行
           if (method.isDefault()) {
               if (privateLookupInMethod == null) {
                   return this.invokeDefaultMethodJava8(proxy, method, args);
              }
               return this.invokeDefaultMethodJava9(proxy, method, args);
          }
      } catch (Throwable var5) {
           throw ExceptionUtil.unwrapThrowable(var5);
      }
       MapperMethod mapperMethod = this.cachedMapperMethod(method);
       return mapperMethod.execute(this.sqlSession, args);
  }

面试:谈谈你对MyBatis执行过程之SQL执行过程理解

 

但最终会调用倒忙mapperMethod::execute() 方法执行,主要是判断是 INSERT 、 UPDATE 、 DELETE 、 SELECT 语句去操作,其中如果是查询的话,还会判断返回值的类型。

public Obje
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值