MyBatis源码学习

 

 

背景

执行一个Sql查询MyBatis做了什么操作?

       //1SqlSessionFactory 创建sqlsession
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //2 这里打开openSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //3 getMapper 创建一个 代理对象MapperRegistry.mapperProxyFactory.newInstance(sqlSession);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
      //4 执行查询
        User user = mapper.selectUser(1L);

1.MyBatis执行过程

MyBatis3.5.2源码

1.SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); 

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      //读取xml 生成一个document
      //通过xpath获取节点内容
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);

      //parser.parse() 通过xpath读取document 生成configuration,并且将
      //mapper.java 类和mapper.xml 进行映射并且存放如 hashmap 里面
      //通过解析mapper.xml里面的sql  每个mapper.java 里面的方法生成一个MapperStatement
      return build(parser.parse());
    } catch (Exception e) {
    
    }
  }
1.配置文件解析入口

1.解析xml生成configuration

解析xml文件中的入参和返参生成实体类,存放到map里面,生成MapperStatement,解析xml生成SqlSource,将xml里面的#替换为? 

private void parseConfiguration(XNode root) {
    try {
      //issue #117 read properties first
      propertiesElement(root.evalNode("properties"));
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      loadCustomVfs(settings);
      loadCustomLogImpl(settings);
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      settingsElement(settings);
      // read it after objectFactory and objectWrapperFactory issue #631
      //???
      environmentsElement(root.evalNode("environments"));
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlerElement(root.evalNode("typeHandlers"));
      //扫描所有的mapper文件添加到hashmap 里面
      //读取配置文件里面mapper.xml的配置
      //调用 mapperRegistry.addMapper(type);
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
  }
2.解析xml生成Configuration

1.1生成MapperStatement

 private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        if ("package".equals(child.getName())) {
          String mapperPackage = child.getStringAttribute("name");
          configuration.addMappers(mapperPackage);
        } else {
          String resource = child.getStringAttribute("resource");
          String url = child.getStringAttribute("url");
          String mapperClass = child.getStringAttribute("class");
          if (resource != null && url == null && mapperClass == null) {
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
        //XMLMapperBuilder.parse.configurationElement
            mapperParser.parse();
          } else if (resource == null && url != null && mapperClass == null) {
            ErrorContext.instance().resource(url);
            InputStream inputStream = Resources.getUrlAsStream(url);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url == null && mapperClass != null) {
            Class<?> mapperInterface = Resources.classForName(mapperClass);
            configuration.addMapper(mapperInterface);
          } else {
            throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
          }
        }
      }
    }
  }
mapperElement解析mappers

1.2

 mapperParser.parse()-configurationElement;
    private void configurationElement(XNode context) {
    try {
      String namespace = context.getStringAttribute("namespace");
      if (namespace == null || namespace.equals("")) {
        throw new BuilderException("Mapper's namespace cannot be empty");
      }
      builderAssistant.setCurrentNamespace(namespace);
      cacheRefElement(context.evalNode("cache-ref"));
      cacheElement(context.evalNode("cache"));
      //解析 生成一个 ParameterMap 并且添加到configuration的 ParameterMap里面
      parameterMapElement(context.evalNodes("/mapper/parameterMap"));
      //解析 生成一个 ResultMap 并且添加到configuration的 ResultMap 里面
      //这里已经生成 ResultMap  是根据xml里面的 xml转换为实体类
      resultMapElements(context.evalNodes("/mapper/resultMap"));
      //这里是解析sql 片段 如:   <sql id="Example_Where_Clause">
      sqlElement(context.evalNodes("/mapper/sql"));
      //解析 生成一个MapperStatement 包含SqlSource 添加到configuration的mappedStatements
    //  解析SQL生成SqlBound ?不是这里完成的
      //这里是解析 具体的<select> parseStatementNode.addMappedStatement
      buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);
    }
  }
2.2解析Mapper.xml的具体的每一个标签内容

1.3 解析Mapper.xml中如parameterMap  

private void parameterMapElement(List<XNode> list) {
    for (XNode parameterMapNode : list) {
      String id = parameterMapNode.getStringAttribute("id");
      String type = parameterMapNode.getStringAttribute("type");
      Class<?> parameterClass = resolveClass(type);
      List<XNode> parameterNodes = parameterMapNode.evalNodes("parameter");
      List<ParameterMapping> parameterMappings = new ArrayList<>();
      for (XNode parameterNode : parameterNodes) {
        String property = parameterNode.getStringAttribute("property");
        String javaType = parameterNode.getStringAttribute("javaType");
        String jdbcType = parameterNode.getStringAttribute("jdbcType");
        String resultMap = parameterNode.getStringAttribute("resultMap");
        String mode = parameterNode.getStringAttribute("mode");
        String typeHandler = parameterNode.getStringAttribute("typeHandler");
        Integer numericScale = parameterNode.getIntAttribute("numericScale");
        ParameterMode modeEnum = resolveParameterMode(mode);
        Class<?> javaTypeClass = resolveClass(javaType);
        JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
        Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler);
        ParameterMapping parameterMapping = builderAssistant.buildParameterMapping(parameterClass, property, javaTypeClass, jdbcTypeEnum, resultMap, modeEnum, typeHandlerClass, numericScale);
        parameterMappings.add(parameterMapping);
      }
      builderAssistant.addParameterMap(id, parameterClass, parameterMappings);
    }
  }
2.3解析mapper.xml文件中resultMap和parameter类型

1.4  解析xml文件中的<resultMap/>:XMLMapperBuilder.resultMapElement

 private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings, Class<?> enclosingType) throws Exception {
    ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
    String type = resultMapNode.getStringAttribute("type",
        resultMapNode.getStringAttribute("ofType",
            resultMapNode.getStringAttribute("resultType",
                resultMapNode.getStringAttribute("javaType"))));
    Class<?> typeClass = resolveClass(type);
    if (typeClass == null) {
      typeClass = inheritEnclosingType(resultMapNode, enclosingType);
    }
    Discriminator discriminator = null;
    List<ResultMapping> resultMappings = new ArrayList<>();
    resultMappings.addAll(additionalResultMappings);
    List<XNode> resultChildren = resultMapNode.getChildren();
    for (XNode resultChild : resultChildren) {
      //  <constructor></constructor> 这个类型的映射
      if ("constructor".equals(resultChild.getName())) {
        processConstructorElement(resultChild, typeClass, resultMappings);
      } else if ("discriminator".equals(resultChild.getName())) {
        discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
      } else {
        List<ResultFlag> flags = new ArrayList<>();
        if ("id".equals(resultChild.getName())) {
          flags.add(ResultFlag.ID);
        }
        resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
      }
    }
    String id = resultMapNode.getStringAttribute("id",
            resultMapNode.getValueBasedIdentifier());
    String extend = resultMapNode.getStringAttribute("extends");
    Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
    ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);
    try {
      //添加到configuration里面的resultMap
      return resultMapResolver.resolve();
    } catch (IncompleteElementException  e) {
      configuration.addIncompleteResultMap(resultMapResolver);
      throw e;
    }
  }
xml文件中的ResultMap 解析

1.5 解析xml文件中的Insert,Select,Update ,delete 标签生成MapperStatement

 MapperRegistry.addMapper 
 public <T> void addMapper(Class<T> type) {
    if (type.isInterface()) {
      if (hasMapper(type)) {
        throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
      }
      boolean loadCompleted = false;
      try {
        knownMappers.put(type, new MapperProxyFactory<>(type));
        // It's important that the type is added before the parser is run
        // otherwise the binding may automatically be attempted by the
        // mapper parser. If the type is already known, it won't try.
        
        /**
         * 添加注解类的 如在mapper.java 类里面添加如
         *   @ResultMap("com.fyp.demo.dao.UserMapper.BaseResultMap")
         *     @Select("select * from user where name=#{name}")
         */
         
        MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
        /**
         * 生成MapperStatement  MapperAnnotationBuilder .parse(parseStatement)
         生成 MapperAnnotationBuilder.parseStatementSqlSource 通过getSqlSourceFromAnnotations
         */
        parser.parse();
        loadCompleted = true;
      } finally {
        if (!loadCompleted) {
          knownMappers.remove(type);
        }
      }
    }
  }
2.3解析Insert,select,update,delete标签生成MapperStatement

1.5.1MapperStatement创建

XMLStatementBuilder:parseStatementNode

  public void parseStatementNode() {
    String id = context.getStringAttribute("id");
    String databaseId = context.getStringAttribute("databaseId");

    if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
      return;
    }

    String nodeName = context.getNode().getNodeName();
    SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
    boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
    boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
    boolean useCache = context.getBooleanAttribute("useCache", isSelect);
    boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);

    // Include Fragments before parsing
    XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);
    includeParser.applyIncludes(context.getNode());

    String parameterType = context.getStringAttribute("parameterType");
    Class<?> parameterTypeClass = resolveClass(parameterType);

    String lang = context.getStringAttribute("lang");
    LanguageDriver langDriver = getLanguageDriver(lang);

    // Parse selectKey after includes and remove them.
    processSelectKeyNodes(id, parameterTypeClass, langDriver);

    // Parse the SQL (pre: <selectKey> and <include> were parsed and removed)
    KeyGenerator keyGenerator;
    String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;
    keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true);
    if (configuration.hasKeyGenerator(keyStatementId)) {
      keyGenerator = configuration.getKeyGenerator(keyStatementId);
    } else {
      keyGenerator = context.getBooleanAttribute("useGeneratedKeys",
          configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
          ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
    }

    //XMLLanguageDriver 将#{}的语句替换为? SqlSourceBuilder.parse
    SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
    //select * from user where id = ?
    StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
    Integer fetchSize = context.getIntAttribute("fetchSize");
    Integer timeout = context.getIntAttribute("timeout");
    String parameterMap = context.getStringAttribute("parameterMap");
    String resultType = context.getStringAttribute("resultType");
    Class<?> resultTypeClass = resolveClass(resultType);
    String resultMap = context.getStringAttribute("resultMap");
    String resultSetType = context.getStringAttribute("resultSetType");
    ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);
    if (resultSetTypeEnum == null) {
      resultSetTypeEnum = configuration.getDefaultResultSetType();
    }
    String keyProperty = context.getStringAttribute("keyProperty");
    String keyColumn = context.getStringAttribute("keyColumn");
    String resultSets = context.getStringAttribute("resultSets");

    //MappedStatement
    builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
        fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
        resultSetTypeEnum, flushCache, useCache, resultOrdered,
        keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
  }
创建MapperStatement

1.6 创建MapperStatement时候解析Sql,SqlSource sqlSource = langDriver.createSqlSource(解析sql替换为?

XMLLanguageDriver:parseScriptNode
XMLScriptBuilder:parseScriptNode具体的sql替换和解析

 public SqlSource parseScriptNode() {
    MixedSqlNode rootSqlNode = parseDynamicTags(context);
    SqlSource sqlSource;
    if (isDynamic) {
      sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
    } else {
      sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
    }
    return sqlSource;
  }
  SqlSourceBuilder:parse
  public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
    ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);

    GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
    String sql = parser.parse(originalSql);
    return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
  }
解析Sql生成SqlSource类,将xml中#替换为?

2.创建DefaultSqlSessionFactory 

2.1创建SqlSession

   public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }
  
DefaultSqlSessionFactory

2.2

DefaultSqlSessionFactory.openSession(openSessionFromDataSource)
   private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      //构建executor  SimpleExecutor
      final Executor executor = configuration.newExecutor(tx, execType);
      log.info("configurantion={}", configuration);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }
3.2 openSession

2.3

Configuration.newExecutor
  public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    //装饰器模式 对Executor进行包装
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }
  
3.3Configuration.newExecutor

3. UserMapper mapper = sqlSession.getMapper(UserMapper.class);

 MapperRegistry.getMapper
     @SuppressWarnings("unchecked")
  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) {
    //MapperProxy . invoke 方法 这里是创建了 mapper.java 的接口对应的 实现类通过代理 创建一个代理类 
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

  public T newInstance(SqlSession sqlSession) {
    final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }
getMapper创建MapperProxy代理类

4.User user = mapper.selectUser(1L);

4.1 调用代理对象执行sql

    @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
      //如果是Object的方法 直接执行
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
      } else if (method.isDefault()) {
        //
        return invokeDefaultMethod(proxy, method, args);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
    //
    /**
     * 缓存执行方法 方法名为key,缓存的是原始方法加上 原始SQL
     * selectTeacher  value=select * from teacher where id = ?
     */
    //公共方法名和类名获取执行的MapperStatement
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
  }
调用MapperProxy.invoke执行mapperMethod.execute
  public Object execute(SqlSession sqlSession, Object[] args) {
    //通过 MapperProxy 的invoke 方法 最后调用这里的execute
    //填充入参 ?替换为具体的值
   //ParamNameResolver 参数替换
    //如何判断是返回list 还是单条?
    //1根据Sql类型(insert.delete ,update select
    // 如果是select 再根据方法返回值判断返回结果类型
    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 {
          //解析入参 ParamNameResolver .getNamedParams
          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;
  }
MapperMethod.execute
  
 @Override
  public <T> T selectOne(String statement, Object parameter) {
    // Popular vote was to return null on 0 results and throw exception on too many.
    //将结果添加到list
    List<T> list = this.selectList(statement, parameter);
    if (list.size() == 1) {
      return list.get(0);
    } else if (list.size() > 1) {
      throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
    } else {
      return null;
    }
  }

    @Override
  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
    //statement=com.fyp.demo.dao.UserMapper.selectUser
      MappedStatement ms = configuration.getMappedStatement(statement);
      //BaseExecutor.query(queryFromDatabase)
      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();
    }
  }
//  BaseExecutor.queryFromDatabase
    private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    List<E> list;
    localCache.putObject(key, EXECUTION_PLACEHOLDER);
    try {
      list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
    } finally {
      localCache.removeObject(key);
    }
    //添加到一级缓存里面
    localCache.putObject(key, list);
    if (ms.getStatementType() == StatementType.CALLABLE) {
      localOutputParameterCache.putObject(key, parameter);
    }
    return list;
  }
DefaultSqlSession.selectOne (selectList)
SimpleExecutor.doQuery
    @Override
  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 根据RoutingStatementHandler 创建具体的Statement 如调用存储过程的 批量的等
      //PreparedStatementHandler 在BaseStatementHandler 里面创建ResultHandler 和ParamenterHandler
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
   // 初始化Sql将?替换为具体的值  SimpleExecutor.prepareStatement
      stmt = prepareStatement(handler, ms.getStatementLog());
     // PreparedStatementHandler
      return handler.query(stmt, resultHandler);
    } finally {
      //关闭 statement
      closeStatement(stmt);
    }
  }

configuration.newStatementHandler(RoutingStatementHandler)
  
  public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {

    switch (ms.getStatementType()) {
      case STATEMENT:
        //SimpleStatementHandler 在构造函数里面创建了 parameterHandler和resultHandler
        delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case PREPARED:
      //BaseStatementHandler(创建parameterHandler,resultSetHandler)
        delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case CALLABLE:
        delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      default:
        throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
    }

  }
  SimpleExecutor.prepareStatement
   private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    Connection connection = getConnection(statementLog);
    //设置statement属性
    stmt = handler.prepare(connection, transaction.getTimeout());
    //参数化 ?号处理为具体的参数 DefaultParameterHandler.setParameters
    handler.parameterize(stmt);
    return stmt;
  }
  
  BaseStatementHandler.prepare 创建statement 
  
    @Override
  public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
    ErrorContext.instance().sql(boundSql.getSql());
    Statement statement = null;
    try {
      statement = instantiateStatement(connection);
      setStatementTimeout(statement, transactionTimeout);
      setFetchSize(statement);
      return statement;
    } catch (SQLException e) {
      closeStatement(statement);
      throw e;
    } catch (Exception e) {
      closeStatement(statement);
      throw new ExecutorException("Error preparing statement.  Cause: " + e, e);
    }
  }
  
  DefaultParameterHandler.setParameters
   @Override
  public void setParameters(PreparedStatement ps) {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings != null) {
      for (int i = 0; i < parameterMappings.size(); i++) {
        ParameterMapping parameterMapping = parameterMappings.get(i);
        if (parameterMapping.getMode() != ParameterMode.OUT) {
          Object value;
          String propertyName = parameterMapping.getProperty();
          if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
            value = boundSql.getAdditionalParameter(propertyName);
          } else if (parameterObject == null) {
            value = null;
          } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
            value = parameterObject;
          } else {
            MetaObject metaObject = configuration.newMetaObject(parameterObject);
            value = metaObject.getValue(propertyName);
          }
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) {
            jdbcType = configuration.getJdbcTypeForNull();
          }
          try {
            //设置参数 将?号填充为具体的参数
            typeHandler.setParameter(ps, i + 1, value, jdbcType);
          } catch (TypeException | SQLException e) {
            throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
          }
        }
      }
    }
  }
创建与数据库交互对象statement,并且初始化Sql参数
  PreparedStatementHandler.query
  
   @Override
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    //PreparedStatementLogger
    ps.execute();
    //获取结果集DefaultResultSetHandler  处理结果集存储到List<T>里面
    //DefaultResultSetHandler.handleResultSets
    return resultSetHandler.handleResultSets(ps);
  }
  
     ps.execute();?
     
     resultSetHandler.handleResultSets(ps);
     DefaultResultSetHandler.handleResultSets(handleResultSet)
     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);
          //storeObject
          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());
    }
  }
  handleRowValues:handleRowValuesForNestedResultMap||handleRowValuesForSimpleResultMap(storeObject)
  
  重要的方法 
  private void storeObject(ResultHandler<?> resultHandler, DefaultResultContext<Object> resultContext, Object rowValue, ResultMapping parentMapping, ResultSet rs) throws SQLException {
    if (parentMapping != null) {
      // extend 类型的
      linkToParents(rs, parentMapping, rowValue);
    } else {
      //DefaultResultHandler .handleResult结果添加到list 里面
      callResultHandler(resultHandler, resultContext, rowValue);
    }
  }
     DefaultResultHandler.handleResult
       @Override
  public void handleResult(ResultContext<?> context) {
    //将结果添加到list 里面
    list.add(context.getResultObject());
  }
执行具体的Sql将结果集保存到list里面

2.相关面试题: 

1.Mapper类都是接口?那么具体的方法在哪里实现的?

    MapperProxyFactory代理类实现的

3.常用类

org.apache.ibatis.builder:

annotation:

  1. MapperAnnotationBuilder解析@Mapper注解
  2. MethodResolver 创建MapperStatement对象
  3. ProviderSqlSource 

xml:

  1. XMLConfigBuilder 解析configuration.xml配置文生成Configuration对象
  2. XMLMapperBuilder 解析Mapper.xml配置文件将接口类和Mapper.xml中namespace对应起来,解析xml中的Result 和Parameter
  3. XMLStatementBuilder 解析select\update\delete 标签 生成MapperStatement(包含SqlSource) 

  

 

 

 

 

 

 

 

 

 

 

 

posted @ 2018-08-23 17:52  暖暖-木木  阅读(260)  评论(0编辑  收藏  举报