Mybatis源碼閱讀之三

    由前面的系列二分析到MapperMethod的execute方法,咱們接着分析MapperMethod。以下List-1:java

    List-1sql

public class MapperMethod {

  private final SqlCommand command;
  private final MethodSignature method;

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

  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);
        }
        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;
  }
...

    List-1中,根據類型來調用不一樣的處理,咱們以insert爲例子分析,調用的就是以下的List-2,首先將傳入Mapper方法上的參數轉換爲SQL參數,以後調用SqlSession的insert方法,注意這個SqlSession是SqlSessionTemplate,咱們來看SqlSessionTemplate的insert方法,如List-3:設計模式

    List-2緩存

case INSERT: {
    Object param = method.convertArgsToSqlCommandParam(args);
    result = rowCountResult(sqlSession.insert(command.getName(), param));
    break;
}

    List-3mybatis

public int insert(String statement, Object parameter) {
    return this.sqlSessionProxy.insert(statement, parameter);
}

以下圖1所示,app

                                                             圖1this

  •     步驟2調用的SqlSessionInterceptor是JDK的代理類;
  •     步驟4中,作了不少事情,好比不一樣類型Executor的生成就是在裏面;
  •     步驟13中,會先清空緩存——由於咱們目前看的是insert更新操做;
  •     步驟17中調用的StatementHandler默認是RoutingStatementHandler,用了Delegate設計模式,默認狀況下委託給PreparedStatementHandler;
  •     步驟23中,涉及了KeyGenerator,因此後面看mybatis中返還主鍵值看這裏;

    步驟17中,RoutingStatementHandler使用了代理模式,將事情所有委託給第三方來作。設計

    步驟1中調用的SqlSessionTemplate,以Template結尾,看着像使用Template模板模式,可是我的以爲是使用了代理模式,由於它內部實現上,大部分事情都委託給了內部類SqlSessionInterceptor。代理

    值得一提的是,BaseExecutor使用了Template模板模式,定義了執行步驟,而後具體實現由其實現類了實現。code

    圖1的過程當中,涉及了事物,使用的是Spring的事物管理。

相關文章
相關標籤/搜索