2021-04-11 MyBatis运行流程-04

查询实现

具体操作

根据id在数据表中查询员工的信息。

源码分析

调用代理对象(MapperProxy)mapper.getEmpById方法:

Employee employee = mapper.getEmpById(1);

因为mapper是一个InvocationHandler,在执行目标方法之前会先执行invoke方法:
在这里插入图片描述
其中MapperMethodexecute()方法:
先判断增删改查
在这里插入图片描述

将参数转换成我们能用的参数,利用参数解析器进行转换,如果参数是单个直接返回,如果是多个包装成Map再返回。

public Object convertArgsToSqlCommandParam(Object[] args) {
      return paramNameResolver.getNamedParams(args);
    }

查询多个,调用selectOne:里面调用selectList查询多个,将他的返回值返回。
在这里插入图片描述
selectList具体实现:
在这里插入图片描述

具体的包装过程:

public static Object wrapToMapIfCollection(Object object, String actualParamName) {
    if (object instanceof Collection) {
      ParamMap<Object> map = new ParamMap<>();
      map.put("collection", object);
      if (object instanceof List) {
        map.put("list", object);
      }
      Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object));
      return map;
    } else if (object != null && object.getClass().isArray()) {
      ParamMap<Object> map = new ParamMap<>();
      map.put("array", object);
      Optional.ofNullable(actualParamName).ifPresent(name -> map.put(name, object));
      return map;
    }
    return object;
  }

}

query方法:

在这里插入图片描述

query查询:

在这里插入图片描述

继续查询:

@SuppressWarnings("unchecked")
  @Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
    //清本地缓存
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      //从本地缓存中拿到key 先查二级缓存,二级缓存中没有时再查一级缓存
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
      if (list != null) {
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {
      //如果缓存中没有,就去数据库中查
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      }
      // issue #601
      deferredLoads.clear();
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
        // issue #482
        clearLocalCache();
      }
    }
    return list;
  }

queryFromDatabase的具体实现:
在这里插入图片描述

doQuery的具体实现:

在这里插入图片描述

其中的query的实现:使用resultSetHandler对查询结果进行封装:使用TypeHandler获取value值。
在这里插入图片描述

创建StatementHandlernewStatementHandler的具体实现:

public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    //实际为创建了PreparedStatementHandler
    StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
    //使用拦截器
    statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    return statementHandler;
  }

调用了RoutingStatementHandler,创建了一个PreparedStatementHandler

在这里插入图片描述
创建了一个PreparedStatementHandler,就是按照构造器创建Handler的过程。
预编译parameterize的具体实现,预编译时会调用parameterHandler对象设置参数:

@Override
  public void parameterize(Statement statement) throws SQLException {
    parameterHandler.setParameters((PreparedStatement) statement);
  }

setParameters的具体实现:
在这里插入图片描述
会拿到类型处理器(TypeHandler),调用类型处理器的setParameterpsPreparedStatement
还会创建resultSetHandler对查询的结果进行处理。
在这里插入图片描述

查询流程总结

利用代理对象执行增删改查,实际使用代理对象的DefaultSqlSession,又使用里面的Executor来执行增删改查,Executor会创建StatementHandler(处理sql语句预编译,设置参数等相关工作),StatementHandler会创建出ParameterHandler(设置预编译参数用的)和ResultSetHandler(处理查询后的结果)。设置参数和处理结果都是用TypeHandler来做的。在整个过程中,TypeHandler进行数据库类型和javaBean类型的映射。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值