zoukankan      html  css  js  c++  java
  • MyBatis源码解析

    首先是mybatis简单的使用Demo(源码基于3.5.1版本):

    String resource = "mybatis-config.xml";
    InputStream inputStream = null;
    try {
        inputStream = Resources.getResourceAsStream(resource);
    } catch (IOException e) {
        e.printStackTrace();
    }
    //构建 SqlSessionFactory
    SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    //从 SqlSessionFactory 中获取 SqlSession
    SqlSession sqlSession = sqlSessionFactory.openSession();
    //获取接口代理对象
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    //执行查询方法
    User user = mapper.selectOne(1L);
    System.out.println(user);
    sqlSession.close();
    

    一、构建 SqlSessionFactory

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

    SqlSessionFactoryBuilder.build()方法:

    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
      try {
        //xml配置文件的解析器
        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
        //返回一个SqlSessionFactory的实现类DefaultSqlSessionFactory
        return build(parser.parse());
      } catch (Exception e) {
        throw ExceptionFactory.wrapException("Error building SqlSession.", e);
      } finally {
        ErrorContext.instance().reset();
        try {
          inputStream.close();
        } catch (IOException e) {
          // Intentionally ignore. Prefer previous error.
        }
      }
    }
    

    主要的方法parser.parse():解析全局配置文件

     //解析全局配置文件 将配置信息封装成一个Configuration
    public Configuration parse() {
      if (parsed) {
        throw new BuilderException("Each XMLConfigBuilder can only be used once.");
      }
      parsed = true;
      //解析配置文件的configuration标签节点,并将配置信息保存到Configuration对象
      parseConfiguration(parser.evalNode("/configuration"));
      //返回一个Configuration对象,包含了所有的全局配置信息和映射文件信息
      return configuration;
    }
    

    parseConfiguration(parser.evalNode("/configuration")):

    //解析全局配置文件configuration标签的各子标签,并将配置信息保存到Configuration对象
    private void parseConfiguration(XNode root) {
      try {
        //解析properties标签
        propertiesElement(root.evalNode("properties"));
        //解析settings标签,并封装成一个Properties
        Properties settings = settingsAsProperties(root.evalNode("settings"));
        loadCustomVfs(settings);
        loadCustomLogImpl(settings);
        //解析typeAliases标签
        typeAliasesElement(root.evalNode("typeAliases"));
        //解析plugins标签
        pluginElement(root.evalNode("plugins"));
        objectFactoryElement(root.evalNode("objectFactory"));
        objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
        reflectorFactoryElement(root.evalNode("reflectorFactory"));
        settingsElement(settings);
        environmentsElement(root.evalNode("environments"));
        databaseIdProviderElement(root.evalNode("databaseIdProvider"));
        typeHandlerElement(root.evalNode("typeHandlers"));
        //解析mappers标签
        mapperElement(root.evalNode("mappers"));
      } catch (Exception e) {
        throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
      }
    }
    

    重点:解析配置文件的mappers标签(sql映射文件位置) mapperElement(root.evalNode("mappers")):

    private void mapperElement(XNode parent) throws Exception {
      if (parent != null) {
        //遍历<mappers>子标签:
        for (XNode child : parent.getChildren()) {
          //使用<package name="org.mybatis.builder"/>子标签
          if ("package".equals(child.getName())) {
            String mapperPackage = child.getStringAttribute("name");
            //保存包名
            configuration.addMappers(mapperPackage);
          } else {
            //<mapper>
            String resource = child.getStringAttribute("resource");
            String url = child.getStringAttribute("url");
            String mapperClass = child.getStringAttribute("class");
            // <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
            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());
              //解析映射文件
              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.");
            }
          }
        }
      }
    }
    

    解析sql映射文件mapperParser.parse():

    public void parse() {
      //该映射文件是否已经加载过
      if (!configuration.isResourceLoaded(resource)) {
        //解析映射文件的mapper标签
        configurationElement(parser.evalNode("/mapper"));
        configuration.addLoadedResource(resource);
        bindMapperForNamespace();
      }
      parsePendingResultMaps();
      parsePendingCacheRefs();
      parsePendingStatements();
    }
    

    解析sql映射文件的mapper标签,configurationElement(parser.evalNode("/mapper")):

    //解析mapper的各个子标签信息并保存在Configuration中
    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"));
        parameterMapElement(context.evalNodes("/mapper/parameterMap"));
        resultMapElements(context.evalNodes("/mapper/resultMap"));
        sqlElement(context.evalNodes("/mapper/sql"));
        //解析所有的增删改查四大标签
        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);
      }
    }
    

    解析增删改查标签buildStatementFromContext(context.evalNodes("select|insert|update|delete")):

    private void buildStatementFromContext(List<XNode> list) {
      //如果标签有指定databaseId
      if (configuration.getDatabaseId() != null) {
        buildStatementFromContext(list, configuration.getDatabaseId());
      }
      buildStatementFromContext(list, null);
    }
    

    接下来buildStatementFromContext(list, null):

    private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
      //遍历所有select|insert|update|delete标签
      for (XNode context : list) {
        //Statement(代表一个增删改查标签)解析器
        final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant, context, requiredDatabaseId);
        try {
          //解析标签
          statementParser.parseStatementNode();
        } catch (IncompleteElementException e) {
          configuration.addIncompleteStatement(statementParser);
        }
      }
    }
    

    解析每增删改查标签 statementParser.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;
      //是否清空缓存,不设置的话 select标签默认为false,其他三个都为为true
      boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
      //是否使用二级缓存,不设置的话 select标签默认为true,其他三个都为为false
      boolean useCache = context.getBooleanAttribute("useCache", isSelect);
      boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);
      //解析include标签,将sql片段包含进来
      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;
      }
      SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
      //Statement类型,STATEMENT:普通的字符串拼接, PREPARED(默认):sql预处理, CALLABLE:可以使用存储过程
      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);
      String keyProperty = context.getStringAttribute("keyProperty");
      String keyColumn = context.getStringAttribute("keyColumn");
      String resultSets = context.getStringAttribute("resultSets");
      //每一个增删改查标签信息最终都会被封装成一个MappedStatement并保存在configuration中
      builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
          fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
          resultSetTypeEnum, flushCache, useCache, resultOrdered,
          keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
    }
    

     

    二、从 SqlSessionFactory 中获取 SqlSession

    SqlSession sqlSession = sqlSessionFactory.openSession();
    

    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
        final Executor executor = configuration.newExecutor(tx, execType);
        //创建DefaultSqlSession,包含configuration,executor
        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();
      }
    }
    

    创建执行器Executor,configuration.newExecutor(tx, execType):

    public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
      executorType = executorType == null ? defaultExecutorType : executorType;
      executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
      Executor executor;
      //根据Executor在全局配置文件中的类型,创建SimpleExecutor(默认)/BatchExecutor/ReuseExecutor
      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);
      }
      //如果开启了二级缓存,则创建CachingExecutor来包装executor
      if (cacheEnabled) {
        executor = new CachingExecutor(executor);
      }
      //使用每一个拦截器包装executor
      executor = (Executor) interceptorChain.pluginAll(executor);
      return executor;
    }
    

     

    三、SqlSession.getMapper():返回接口的代理对象

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

    getMapper:

    public <T> T getMapper(Class<T> type) {
      //从configuration对象中获取
      return configuration.getMapper(type, this);
    }
    
    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
      return mapperRegistry.getMapper(type, sqlSession);
    }
    
    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
      //根据接口类型在knownMappers中获取对应得MapperProxyFactory
      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);
      }
    }
    
    public T newInstance(SqlSession sqlSession) {
      //MapperProxy实现了InvocationHandler接口,包含sqlSession(包含configuration,executor)
      final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
      return newInstance(mapperProxy);
    }
    
    protected T newInstance(MapperProxy<T> mapperProxy) {
      //利用jdk动态代理创建代理对象
      return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
    }
    

     

    四、执行查询方法:

    User user = mapper.selectOne(1L);
    

    mapper是一个代理对象,实际是执行MapperProxy(implements InvocationHandler)的invoke方法:

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      try {
        if (Object.class.equals(method.getDeclaringClass())) {
          //直接执行Object对象中定义的方法
          return method.invoke(this, args);
          //是否是接口的默认方法(jdk1.8)
        } else if (isDefaultMethod(method)) {
          return invokeDefaultMethod(proxy, method, args);
        }
      } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
      }
      //MapperMethod代表当前执行的方法,包含了configuration对象
      final MapperMethod mapperMethod = cachedMapperMethod(method);
      //执行增删改查方法
      return mapperMethod.execute(sqlSession, args);
    }
    

    cachedMapperMethod(method):

    private MapperMethod cachedMapperMethod(Method method) {
      //先从methodCache中获取,如果不存在就new一个MapperMethod添加到methodCache并返回
      return methodCache.computeIfAbsent(method, k -> new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
    }
    

    mapperMethod.execute(sqlSession, args):执行具体的增删改方法

    public Object execute(SqlSession sqlSession, Object[] args) {
      Object result;
      //判断执行sql语言的类型,这里是select类型
      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);
           //返回值为Map时
          } else if (method.returnsMap()) {
            result = executeForMap(sqlSession, args);
            //返回值为游标
          } else if (method.returnsCursor()) {
            result = executeForCursor(sqlSession, args);
          } else {
            //返回值为单个
            //将方法参数转换成sql语言可以使用的形式
            Object param = method.convertArgsToSqlCommandParam(args);
            //查询单条记录command.getName()为方法的全限定名
            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;
    }
    

    method.convertArgsToSqlCommandParam(args):参数解析

    public Object convertArgsToSqlCommandParam(Object[] args) {
      return paramNameResolver.getNamedParams(args);
    }
    
    public Object getNamedParams(Object[] args) {
      //参数的数量
      final int paramCount = names.size();
      if (args == null || paramCount == 0) {
        return null;
        //如果方法参数没有使用@Param注解命名,且方法只有一个参数,直接返回该参数值
      } else if (!hasParamAnnotation && paramCount == 1) {
        return args[names.firstKey()];
      } else {
        //如果是多个参数则封装成一个Map
        final Map<String, Object> param = new ParamMap<>();
        int i = 0;
        for (Map.Entry<Integer, String> entry : names.entrySet()) {
          param.put(entry.getValue(), args[entry.getKey()]);
          // add generic param names (param1, param2, ...)
          final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
          // ensure not to overwrite parameter named with @Param
          if (!names.containsValue(genericParamName)) {
            param.put(genericParamName, args[entry.getKey()]);
          }
          i++;
        }
        return param;
      }
    }
    

    sqlSession.selectOne(command.getName(), param):查询单条记录

    @Override
    public <T> T selectOne(String statement, Object parameter) {
      // 查询单条其实也是和查询多条记录一样返回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;
      }
    }
    

    selectList(statement, parameter):

    @Override
    public <E> List<E> selectList(String statement, Object parameter) {
      return this.selectList(statement, parameter, RowBounds.DEFAULT);
    }
    
    @Override
    public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
      try {
        //configuration中获取到MappedStatement(代表一个增删改查标签的所有信息)
        MappedStatement ms = configuration.getMappedStatement(statement);
        //执行器执行查询操作,wrapCollection(parameter)处理参数是集合的情况
        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.query():

    //CachingExecutor:
    @Override
    public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
      //BoundSql 代表sql的详细信息,包括sql语言,参数值以及参数在sql语句中的映射关系
      BoundSql boundSql = ms.getBoundSql(parameterObject);
      //使用了二级缓存,所有需要生成缓存的key
      CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
      return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }
    

    query(ms, parameterObject, rowBounds, resultHandler, key, boundSql):

    @Override
    public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
        throws SQLException {
      //如果映射文件使用了 </cache>标签 ,就能获取到缓存对象
      Cache cache = ms.getCache();
      if (cache != null) {
        flushCacheIfRequired(ms);
        if (ms.isUseCache() && resultHandler == null) {
          ensureNoOutParams(ms, boundSql);
          @SuppressWarnings("unchecked")
          //先从缓存中获取,存在就直接返回,不存在再查询
          List<E> list = (List<E>) tcm.getObject(cache, key);
          if (list == null) {
            //delegate,就是真正执行sql的Executor(当前为),CachingExecutor只是对其的一层包装
            list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
            tcm.putObject(cache, key, list); // issue #578 and #116
          }
          return list;
        }
      }
      return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }
    

    delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql):

    //BaseExecutor:
    public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
      ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
      if (closed) {
        throw new ExecutorException("Executor was closed.");
      }
      //是否需要清本地缓存
      if (queryStack == 0 && ms.isFlushCacheRequired()) {
        clearLocalCache();
      }
      List<E> list;
      try {
        queryStack++;
        //先从本地缓存中获取
        list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
        if (list != null) {
          handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
        } else {
          //缓存不存在,再从数据库中查
          list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
        }
      } finally {
        queryStack--;
      }
      if (queryStack == 0) {
        for (DeferredLoad deferredLoad : deferredLoads) {
          deferredLoad.load();
        }
        // issue #601
        deferredLoads.clear();
        if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
          // issue #482
          clearLocalCache();
        }
      }
      return list;
    }
    

    queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql):

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

    doQuery(ms, parameter, rowBounds, resultHandler, boundSql):

    @Override
    public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
      //原生jdbc的Statement
      Statement stmt = null;
      try {
        Configuration configuration = ms.getConfiguration();
        //StatementHandler(用于获取Statement)
        StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
        //获取PreparedStatement
        stmt = prepareStatement(handler, ms.getStatementLog());
        //执行sql,返回结果集
        return handler.query(stmt, resultHandler);
      } finally {
        closeStatement(stmt);
      }
    }
    

    configuration.newStatementHandler(...):获取StatementHandler对象

    public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
      //RoutingStatementHandler是一个包装对象
      StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
      //使用每一个拦截器包装statementHandler
      statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
      return statementHandler;
    }
    
    public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
      //根据MappedStatement的类型创建一个实际使用的StatementHandler,默认为PREPARED
      switch (ms.getStatementType()) {
        case STATEMENT:
          delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
          break;
        case PREPARED:
          //chuan'jPreparedStatementHandler
          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());
      }
    
    }
    
    public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
      //父类为BaseStatementHandler
      super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
    }
    
    protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
      this.configuration = mappedStatement.getConfiguration();
      this.executor = executor;
      this.mappedStatement = mappedStatement;
      this.rowBounds = rowBounds;
    
      this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
      this.objectFactory = configuration.getObjectFactory();
    
      if (boundSql == null) { // issue #435, get the key before calculating the statement
        generateKeys(parameterObject);
        boundSql = mappedStatement.getBoundSql(parameterObject);
      }
    
      this.boundSql = boundSql;
      //创建参数处理器,会经过拦截器链的包装
      this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
      //创建结果集处理器,会经过拦截器链的包装
      this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
    }
    

    stmt = prepareStatement(handler, ms.getStatementLog()):获取Statement(PreparedStatement)

    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
      Statement stmt;
      //获取连接(Transaction.getConnection -> DataSource.getConnection)
      Connection connection = getConnection(statementLog);
      //预编译sql,获取Statement(Connection.prepareStatement)
      stmt = handler.prepare(connection, transaction.getTimeout());
      //使用parameterHandler给预编译的sql设置参数
      handler.parameterize(stmt);
      return stmt;
    }
    

    handler.query(stmt, resultHandler):执行sql语言

    @Override
    public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
      PreparedStatement ps = (PreparedStatement) statement;
      //执行查询
      ps.execute();
      //使用resultSetHandler处理结果集,并返回
      return resultSetHandler.handleResultSets(ps);
    }

     
    
    
  • 相关阅读:
    CF763C Timofey and Remoduling
    CF762E Radio Stations
    CF762D Maximum Path
    CF763B Timofey and Rectangles
    URAL1696 Salary for Robots
    uva10884 Persephone
    LA4273 Post Offices
    SCU3037 Painting the Balls
    poj3375 Network Connection
    Golang zip压缩文件读写操作
  • 原文地址:https://www.cnblogs.com/qzlcl/p/11299517.html
Copyright © 2011-2022 走看看