• 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 解析selectupdatedelete 标签 生成MapperStatement(包含SqlSource) 

      

     

     

  • 相关阅读:
    Java实现 LeetCode 209 长度最小的子数组
    Java实现 蓝桥杯 图书排列(全排列)
    Java实现 蓝桥杯 图书排列(全排列)
    Java实现 蓝桥杯 图书排列(全排列)
    C++11 FAQ中文版--转
    rtsp交互命令简介及过程参数描述
    PS流格式
    经典系统windows xp sp3官方原版下载(附XP序列号)
    Darwin Streaming Server 简介
    jrtplib跨网络通讯NAT穿透问题解决方法
  • 原文地址:https://www.cnblogs.com/fanBlog/p/9525312.html
Copyright © 2020-2023  润新知