美文网首页
mybatis执行流程图-2

mybatis执行流程图-2

作者: engineer_tang | 来源:发表于2020-08-16 08:17 被阅读0次

1. MapperMethod说明

mybatis在进行增删改查时,都是通过代理类MapperProxy生成对应的代理对象完成的,每一个增删改查方法都有对应的代理执行体MapperMethodInvoker会缓存到MapperProxyFactory的methodCache指向的集合对象中。而MapperMethodInvoker最终调用的是MapperMethod类的execute方法。

  public Object execute(SqlSession sqlSession, Object[] args) {
    Object result;
    switch (command.getType()) {
      case INSERT: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.insert(command.getName(), param));
        break;
      }
      case UPDATE: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.update(command.getName(), param));
        break;
      }
      case DELETE: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.delete(command.getName(), param));
        break;
      }
      case SELECT:
        if (method.returnsVoid() && method.hasResultHandler()) {
          executeWithResultHandler(sqlSession, args);
          result = null;
        } else if (method.returnsMany()) {
          result = executeForMany(sqlSession, args);
        } else if (method.returnsMap()) {
          result = executeForMap(sqlSession, args);
        } else if (method.returnsCursor()) {
          result = executeForCursor(sqlSession, args);
        } else {
          Object param = method.convertArgsToSqlCommandParam(args);
          result = sqlSession.selectOne(command.getName(), param);
          if (method.returnsOptional()
              && (result == null || !method.getReturnType().equals(result.getClass()))) {
            result = Optional.ofNullable(result);
          }
        }
        break;
      case FLUSH:
        result = sqlSession.flushStatements();
        break;
      default:
        throw new BindingException("Unknown execution method for: " + command.getName());
    }
    if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
      throw new BindingException("Mapper method '" + command.getName()
          + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
    }
    return result;
  }

这里有两个比较重要的静态内部类SqlCommand 和MethodSignature ,下面对这两个类进行详细分析。

2. SqlCommand 分析

通过SqlCommand的实现类可以知道,它只有两个属性分别是name和type, 在进行实例化的时候就要判断出name和type的值。判断业务逻辑是:
1)通过入参把mapperInterface, methodName, declaringClass, configuration作为入参调用resolveMappedStatement方法返回一个MappedStatement对象。

  1. 如果返回的MappedStatement对象为空,就判断方法上是否有@Flush注解,不存在该注解时直接抛出BindingException异常,存在该注解时,就把name指向null,并且把type设置值为SqlCommandType.FLUSH。
  2. 如果返回的MappedStatement对象不为空,就通过该对象赋值给name和type属性,然后判断type的值若为SqlCommandType.UNKNOWN,就抛出BindingException异常。
    type的取值如下
public enum SqlCommandType {
  UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH
}

这里顺便贴下resolveMappedStatement方法的实现,有兴趣的可以通过mybatis源码看更详细的实现细节:

    private MappedStatement resolveMappedStatement(Class<?> mapperInterface, String methodName,
        Class<?> declaringClass, Configuration configuration) {
      String statementId = mapperInterface.getName() + "." + methodName;
      if (configuration.hasStatement(statementId)) {
        return configuration.getMappedStatement(statementId);
      } else if (mapperInterface.equals(declaringClass)) {
        return null;
      }
      for (Class<?> superInterface : mapperInterface.getInterfaces()) {
        if (declaringClass.isAssignableFrom(superInterface)) {
          MappedStatement ms = resolveMappedStatement(superInterface, methodName,
              declaringClass, configuration);
          if (ms != null) {
            return ms;
          }
        }
      }
      return null;
    }

3. MethodSignature 分析

    public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {
      Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
      if (resolvedReturnType instanceof Class<?>) {
        this.returnType = (Class<?>) resolvedReturnType;
      } else if (resolvedReturnType instanceof ParameterizedType) {
        this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType();
      } else {
        this.returnType = method.getReturnType();
      }
      this.returnsVoid = void.class.equals(this.returnType);
      this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
      this.returnsCursor = Cursor.class.equals(this.returnType);
      this.returnsOptional = Optional.class.equals(this.returnType);
      this.mapKey = getMapKey(method);
      this.returnsMap = this.mapKey != null;
      this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
      this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
      this.paramNameResolver = new ParamNameResolver(configuration, method);
    }
  1. 这段代码的作用主要是判断返回的数据类型,以及判断返回类型的其他属性,例如是否返回为void、是否返回多条记录,是否返回游标等信息。

相关文章

网友评论

      本文标题:mybatis执行流程图-2

      本文链接:https://www.haomeiwen.com/subject/buxtjktx.html