Talk about the MapperMethod of Mybatis' binding module

Offer arrives, dig friends to pick up! I am participating in the 2022 Spring Recruitment Check-In Event, click to view the event details .

Talk about the MapperMethod of Mybatis' binding module

Call the execute() method of MapperMethod through MapperProxy,

Let's take a look at the constructor of MapperMethod:

public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
    this.command = new SqlCommand(config, mapperInterface, method);
    this.method = new MethodSignature(config, mapperInterface, method);
  }
复制代码

SqlCommand is used to record the unique identifier of sql statement and the type of sql statement: UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH

public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
      final String methodName = method.getName();
      final Class<?> declaringClass = method.getDeclaringClass();
      MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass,
          configuration);
      if (ms == null) {
        if (method.getAnnotation(Flush.class) != null) {
          name = null;
          type = SqlCommandType.FLUSH;
        } else {
          throw new BindingException("Invalid bound statement (not found): "
              + mapperInterface.getName() + "." + methodName);
        }
      } else {
        name = ms.getId();
        type = ms.getSqlCommandType();
        if (type == SqlCommandType.UNKNOWN) {
          throw new BindingException("Unknown execution method for: " + name);
        }
      }
    }
复制代码
  1. Get the method name corresponding to the Mapper interface
  2. Get the type of the Mapper interface
  3. Call the resolveMappedStatement() method to return MappedStatement, MappedStatement is the object parsed by SQL in the xml file, and id is the interface name + method name
  4. set name and type

And MapperMethod saves some information about the method

Take a look at the execute() method of MapperMethod:

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;
  }
复制代码
  1. Call according to the type of SQL statement, corresponding to INSERT, UPDATE, DELETE, the logic is similar, all call the convertArgsToSqlCommandParam() method to process the parameters, and then call the sqlSession to execute the sql The final returned result is processed by rowCountResult
  2. For the SELECT statement, select different execute methods to execute according to the return type of the method, and finally call the method in SqlSession

Summarize

At this point, the binding module of mybatis is almost finished. The general process is that MapperRegistry obtains the instance of MapperProxyFactory according to different Mapper interfaces, then calls the newInstance() method, uses the MapperProxy proxy class to obtain the dynamic proxy object of the Mapper interface, and finally calls the execute() of MapperMethod. Pass in the parameters and the encapsulated sql object information, and execute the sql statement

Guess you like

Origin juejin.im/post/7079385848885559304