Mybatis源码分析-执行模块

来源:互联网 发布:金属徽章定制价格淘宝 编辑:程序博客网 时间:2024/05/21 10:06

执行模块打算分几篇记录,先大概了解下整体流程,再详细讲些个人感觉重要的点。
接着上篇例子讲

    String resource = "configs/mybatis-config.xml";        Reader reader = Resources.getResourceAsReader(resource);        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();        SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(reader);        SqlSession session = sqlSessionFactory.openSession();        try {            AppMapper mapper = session.getMapper(AppMapper.class);            List<App> blog = mapper.selectByFilter(null);            System.out.println(JsonUtil.objectToJson(blog));        } finally {            session.close();        }

上篇已经粗略介绍过配置初始化的代码,这篇来看看 代码中try块中的代码!
1 AppMapper mapper = session.getMapper(AppMapper.class); 获取代理mapper类
从上篇应该知道,此时的session的真正执行者是DefaultSqlSession,来看看其getMapper方法

  @Override  public <T> T getMapper(Class<T> type) {    return configuration.<T>getMapper(type, this);  }

实现了Configuration的getMapper方法

  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {    return mapperRegistry.getMapper(type, sqlSession);  }

实现了MapperRegistry的getMapper方法

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

实现了 MapperProxyFactory的newInstance方法

  protected T newInstance(MapperProxy<T> mapperProxy) {    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);  }  public T newInstance(SqlSession sqlSession) {    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);    return newInstance(mapperProxy);  }

终于到正主了,可以看到,在这里实现了代理了,代理是MapperProxy并且返回

2 List blog = mapper.selectByFilter(null);
获取到mapper代理后,执行了selectByFilter方法,既然是代理类,执行的方法就应该是MapperProxy类中的invoke方法,我们来看看

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    try {      if (Object.class.equals(method.getDeclaringClass())) {        return method.invoke(this, args);      } else if (isDefaultMethod(method)) {        return invokeDefaultMethod(proxy, method, args);      }    } catch (Throwable t) {      throw ExceptionUtil.unwrapThrowable(t);    }    final MapperMethod mapperMethod = cachedMapperMethod(method);    return mapperMethod.execute(sqlSession, args);  }

Object.class.equals(method.getDeclaringClass()) 这个判断基本上可以没用了,我们一般都是用接口
往下走,出现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);        }        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;  }

我们的例子中走的是 executeForMany方法,返回列表

  private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {    List<E> result;    Object param = method.convertArgsToSqlCommandParam(args);    if (method.hasRowBounds()) {      RowBounds rowBounds = method.extractRowBounds(args);      result = sqlSession.<E>selectList(command.getName(), param, rowBounds);    } else {      result = sqlSession.<E>selectList(command.getName(), param);    }    // issue #510 Collections & arrays support    if (!method.getReturnType().isAssignableFrom(result.getClass())) {      if (method.getReturnType().isArray()) {        return convertToArray(result);      } else {        return convertToDeclaredCollection(sqlSession.getConfiguration(), result);      }    }    return result;  }

好吧,绕了大圈 ,又回到sqlSession.selectList方法

 public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {    try {      MappedStatement ms = configuration.getMappedStatement(statement);      return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);    } catch (Exception e) {      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);    } finally {      ErrorContext.instance().reset();    }  }

终于到了执行器这里了,此时的executor是CachingExecutor代理,先从缓存过一遍,如果不存在,则从库中获取

  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {    try {      Set<Method> methods = signatureMap.get(method.getDeclaringClass());      if (methods != null && methods.contains(method)) {        return interceptor.intercept(new Invocation(target, method, args));      }      return method.invoke(target, args);    } catch (Exception e) {      throw ExceptionUtil.unwrapThrowable(e);    }  }

从代理中走了一圈,看看是否有插件的存在,有插件则走插件,无插件走原方法,咱这里没插件!

  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {    BoundSql boundSql = ms.getBoundSql(parameterObject);    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);  }

这里先不讲缓存了,继续经过一级缓存的判断,没有的情况下,继续执行SimpleExecutor执行器

  list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;

二级缓存的判断,也没有,则

list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);

从数据库中获取数据

  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {    Statement stmt = null;    try {      Configuration configuration = ms.getConfiguration();      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);      stmt = prepareStatement(handler, ms.getStatementLog());      return handler.<E>query(stmt, resultHandler);    } finally {      closeStatement(stmt);    }  }

终于出现Statement关键类了
StatementHandler 四大类之一

  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {    Statement stmt;    Connection connection = getConnection(statementLog);    stmt = handler.prepare(connection, transaction.getTimeout());    handler.parameterize(stmt);    return stmt;  }

分析下 这块
Connection connection = getConnection(statementLog);
这个方法里面涉及到数据连接池(当然你也可以配置不用连接池,但为什么不用呢?),也就是说 优先从连接池中获取链接,如果过期,则删除过期链接重新生成一个链接。连接池具体怎么样不是本篇内容。然后返回的链接时一个ConnectionLogger的代理,来看看invoke内容

  public Object invoke(Object proxy, Method method, Object[] params)      throws Throwable {    try {      if (Object.class.equals(method.getDeclaringClass())) {        return method.invoke(this, params);      }          if ("prepareStatement".equals(method.getName())) {        if (isDebugEnabled()) {          debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);        }                PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);        stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);        return stmt;      } else if ("prepareCall".equals(method.getName())) {        if (isDebugEnabled()) {          debug(" Preparing: " + removeBreakingWhitespace((String) params[0]), true);        }                PreparedStatement stmt = (PreparedStatement) method.invoke(connection, params);        stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);        return stmt;      } else if ("createStatement".equals(method.getName())) {        Statement stmt = (Statement) method.invoke(connection, params);        stmt = StatementLogger.newInstance(stmt, statementLog, queryStack);        return stmt;      } else {        return method.invoke(connection, params);      }    } catch (Throwable t) {      throw ExceptionUtil.unwrapThrowable(t);    }  }

好吗 在使用connection生成Statment的时候,就执行了该invoke内容了。

    stmt = PreparedStatementLogger.newInstance(stmt, statementLog, queryStack);

又使用代理,返回PreparedStatementLogger代理
到此 Statement 已经创建好了

 public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {    try {      if (Object.class.equals(method.getDeclaringClass())) {        return method.invoke(this, params);      }                if (EXECUTE_METHODS.contains(method.getName())) {        if (isDebugEnabled()) {          debug("Parameters: " + getParameterValueString(), true);        }        clearColumnInfo();        if ("executeQuery".equals(method.getName())) {          ResultSet rs = (ResultSet) method.invoke(statement, params);          return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);        } else {          return method.invoke(statement, params);        }      } else if (SET_METHODS.contains(method.getName())) {        if ("setNull".equals(method.getName())) {          setColumn(params[0], null);        } else {          setColumn(params[0], params[1]);        }        return method.invoke(statement, params);      } else if ("getResultSet".equals(method.getName())) {        ResultSet rs = (ResultSet) method.invoke(statement, params);        return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);      } else if ("getUpdateCount".equals(method.getName())) {        int updateCount = (Integer) method.invoke(statement, params);        if (updateCount != -1) {          debug("   Updates: " + updateCount, false);        }        return updateCount;      } else {        return method.invoke(statement, params);      }    } catch (Throwable t) {      throw ExceptionUtil.unwrapThrowable(t);    }  }

接下来Statement每一个操作都会进入PreparedStatementLogger的invoke方法中 ,可见 它只处理executeQuery,setNull,getResultSet,getUpdateCount的方法调用,其他还是调用原方法
接下来 是ParameterHandler,四大类之一,主要是处理参数的操作

  @Override  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {    PreparedStatement ps = (PreparedStatement) statement;    ps.execute();    return resultSetHandler.<E> handleResultSets(ps);  }

走到PreparedStatementHandler中的query方法,执行sql语句了,接下来就是对结果集的处理了,ResultSetHandler四大类之一,主要处理结果数据转换!

 public List<Object> handleResultSets(Statement stmt) throws SQLException {    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());    final List<Object> multipleResults = new ArrayList<Object>();    int resultSetCount = 0;    //获得执行的字段、字段类型等信息    ResultSetWrapper rsw = getFirstResultSet(stmt);//获得结果配置信息    List<ResultMap> resultMaps = mappedStatement.getResultMaps();    int resultMapCount = resultMaps.size();    validateResultMapsCount(rsw, resultMapCount);    while (rsw != null && resultMapCount > resultSetCount) {      ResultMap resultMap = resultMaps.get(resultSetCount);      //对结果数据进行处理,生成实体类,循环行数据,给实体类赋值,方法中还需要考虑到类型转换器      handleResultSet(rsw, resultMap, multipleResults, null);      rsw = getNextResultSet(stmt);      cleanUpAfterHandlingResultSet();      resultSetCount++;    }    String[] resultSets = mappedStatement.getResultSets();    if (resultSets != null) {      while (rsw != null && resultSetCount < resultSets.length) {        ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);        if (parentMapping != null) {          String nestedResultMapId = parentMapping.getNestedResultMapId();          ResultMap resultMap = configuration.getResultMap(nestedResultMapId);          handleResultSet(rsw, resultMap, null, parentMapping);        }        rsw = getNextResultSet(stmt);        cleanUpAfterHandlingResultSet();        resultSetCount++;      }    }    return collapseSingleResultList(multipleResults);  }
  private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException {    try {      if (parentMapping != null) {        handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);      } else {        if (resultHandler == null) {          DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);          //赋值          handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);          multipleResults.add(defaultResultHandler.getResultList());        } else {          handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);        }      }    } finally {      // issue #228 (close resultsets)      closeResultSet(rsw.getResultSet());    }  }
  private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)      throws SQLException {    DefaultResultContext<Object> resultContext = new DefaultResultContext<Object>();    skipRows(rsw.getResultSet(), rowBounds);    while (shouldProcessMoreRows(resultContext, rowBounds) && rsw.getResultSet().next()) {      ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);      Object rowValue = getRowValue(rsw, discriminatedResultMap);      storeObject(resultHandler, resultContext, rowValue, parentMapping, rsw.getResultSet());    }  }
//获取数据赋值  private boolean applyPropertyMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, ResultLoaderMap lazyLoader, String columnPrefix)      throws SQLException {    final List<String> mappedColumnNames = rsw.getMappedColumnNames(resultMap, columnPrefix);    boolean foundValues = false;    final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();    //循环执行获取行数据    for (ResultMapping propertyMapping : propertyMappings) {    //字段      String column = prependPrefix(propertyMapping.getColumn(), columnPrefix);      if (propertyMapping.getNestedResultMapId() != null) {        // the user added a column attribute to a nested result map, ignore it        column = null;      }      if (propertyMapping.isCompositeResult()          || (column != null && mappedColumnNames.contains(column.toUpperCase(Locale.ENGLISH)))          || propertyMapping.getResultSet() != null) {          //真实值        Object value = getPropertyMappingValue(rsw.getResultSet(), metaObject, propertyMapping, lazyLoader, columnPrefix);        // issue #541 make property optional        final String property = propertyMapping.getProperty();        if (property == null) {          continue;        } else if (value == DEFERED) {          foundValues = true;          continue;        }        if (value != null) {          foundValues = true;        }        if (value != null || (configuration.isCallSettersOnNulls() && !metaObject.getSetterType(property).isPrimitive())) {          // gcode issue #377, call setter on nulls (value is not 'found')          //通过该方法进行赋值,通过set方法将值set进去          metaObject.setValue(property, value);        }      }    }    return foundValues;  }
  private Object getRowValue(ResultSetWrapper rsw, ResultMap resultMap) throws SQLException {    final ResultLoaderMap lazyLoader = new ResultLoaderMap();    //获得实体类    Object rowValue = createResultObject(rsw, resultMap, lazyLoader, null);    if (rowValue != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {      final MetaObject metaObject = configuration.newMetaObject(rowValue);      boolean foundValues = this.useConstructorMappings;      if (shouldApplyAutomaticMappings(resultMap, false)) {        foundValues = applyAutomaticMappings(rsw, resultMap, metaObject, null) || foundValues;      }      //实体类赋值      foundValues = applyPropertyMappings(rsw, resultMap, metaObject, lazyLoader, null) || foundValues;      foundValues = lazyLoader.size() > 0 || foundValues;      rowValue = (foundValues || configuration.isReturnInstanceForEmptyRow()) ? rowValue : null;    }    return rowValue;  }
  private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, ResultLoaderMap lazyLoader, String columnPrefix) throws SQLException {    this.useConstructorMappings = false; // reset previous mapping result    final List<Class<?>> constructorArgTypes = new ArrayList<Class<?>>();    final List<Object> constructorArgs = new ArrayList<Object>();    //生成实体类,这里用到ObjectFactory,即配置中介绍的可以实现实体类初始化    Object resultObject = createResultObject(rsw, resultMap, constructorArgTypes, constructorArgs, columnPrefix);    if (resultObject != null && !hasTypeHandlerForResultObject(rsw, resultMap.getType())) {      final List<ResultMapping> propertyMappings = resultMap.getPropertyResultMappings();      //循环配置结果集      for (ResultMapping propertyMapping : propertyMappings) {        // 判断是否延迟加载        if (propertyMapping.getNestedQueryId() != null && propertyMapping.isLazy()) {          resultObject = configuration.getProxyFactory().createProxy(resultObject, lazyLoader, configuration, objectFactory, constructorArgTypes, constructorArgs);          break;        }      }    }    this.useConstructorMappings = (resultObject != null && !constructorArgTypes.isEmpty()); // set current mapping result    return resultObject;  }

好了 获得结果就返回,最后关闭连接,不过这里用到连接池,不会真正的关闭。
这两篇mybatis有代码,而且代码占多,并且没有注释,还是想着自己看懂就行了毕竟是粗略的过一下,这种想法不是很好,接下来几篇尽量能注释好吧!!
接下来将逐步分析以下几个模块,一个个来吧!!
1 数据源
2 缓存
3 事务
4 插件

原创粉丝点击