mybatis源码学习之流程分析

mybatis源码学习之流程分析

  • 架构设计原理
  • 主要构件
  • 总体流程
    • 初始化过程
    • 执行sql流程
  • 学习收货

架构设计原理

我们把mybatis的架构分为三层

  • api接口层:
    配置信息维护接口;增删改查接口,基于statementId和mapper接口的调用方式.
    这一层就是提供给我们使用的接口api,我们可以通过api直接操作数据库
  • 数据处理层:
    参数映射(ParamterHandler) -> SQL解析(SqlSource) -> SQL执行(Executor) -> 结果集映射(ResultSetGandler)
    这一层负责具体的SQL查找、解析、执行、结果集封装等,主要就是完成一次数据库操作
  • 基础支撑层:
    事务管理、连接池管理、缓存机制
    基于注解和XML的SQl语句配置方式

主要构件

  • SqlSession:mybatis工作的主要顶层api,表示和数据库交互的会话
  • Executor:mybatis执行器,mybatis调度的核心,负责SQL语句的生成和缓存的维护
  • StatementHandler:负责对JDBC Statement的操作,设置参数、将statement结果集转换成list集合
  • ParamterHandler:将我们传入的参数转换为JDBC Statement需要的参数
  • ResultSetHandler:将JDBC返回的结果集转换成List集合
  • TypeHandler:负责java数据类型和jdbc数据类型之间的转换
  • MappedStatement:封装了一条<增删改查>的节点
  • SqlSource:根据我们传递的参数对象,动态生成SQL语句,并将信息封装到BoundSql中
  • BoundSql:动态生成SQL语句以及相应的参数信息

总体流程

  • 加载配置文件并初始化
    配置来源于两个地方一个是注解一个是核心配置信息和映射配置信息,将核心配置文件的内容解析封装到configuration将映射配置信息加载为多个mappedstatement对象,储存在内存中
    接收调用请求
  • 调用api接口层
    将sql的statementid和参数传入,将请求向下传递处理
  • 处理操作请求
    获取传入的请求
    根据statementid查询相应的mappedstatement对象
    根据传入的参数解析mappedstatement对象,得到最终要执行的sql
    获取数据库连接,将sql传入参数到数据库执行,并得到执行结果ResultSet,并根据TypeHandler完成类型转换得到处理后的结果并返回
    释放资源

初始化过程

// 将我们的核心配置文件解析成一个字节输入流
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
// 初始化工作开始
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

SqlSessionFactoryBuilder().build(resourceAsStream)做了哪些事?

public SqlSessionFactory build(InputStream inputStream) {
     
    //调用了重载方法
    return build(inputStream, null, null);
}

build(inputStream, null, null)
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
     
    try {
     
        // 创建 XMLConfigBuilder, XMLConfigBuilder是专门解析mybatis的核心配置文件的类
        XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
        // 在一次调用build重载方法 parser.parse()返回的是configuration对象
        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()
public Configuration parse() {
     
    // 判断是否解析过
    if (parsed) {
     
        throw new BuilderException("Each XMLConfigBuilder can only be used once.");
    }
    // 设置为已解析
    parsed = true;
    ///parser是,是核心配置文件中的父标签
    // 使用XPathParser解析器对象,读取核心配置文件中 configuration 节点下的节点数据解析
    parseConfiguration(parser.evalNode("/configuration"));
    return configuration;
}

parseConfiguration(parser.evalNode("/configuration"));
这个方法就是对configuration标签下的各种节点的解析
private void parseConfiguration(XNode root) {
     
    try {
     
        // 解析  标签
        propertiesElement(root.evalNode("properties"));
        // 解析  标签
        Properties settings = settingsAsProperties(root.evalNode("settings"));
        // 加载自定义的 VFS 实现类
        loadCustomVfs(settings);
        // 解析  标签
        typeAliasesElement(root.evalNode("typeAliases"));
        // 解析  标签
        pluginElement(root.evalNode("plugins"));
        // 解析  标签
        objectFactoryElement(root.evalNode("objectFactory"));
        // 解析  标签
        objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
        // 解析  标签
        reflectorFactoryElement(root.evalNode("reflectorFactory"));
        // 赋值  到 Configuration 属性
        settingsElement(settings);
        // 解析  标签
        environmentsElement(root.evalNode("environments"));
        // 解析  标签
        databaseIdProviderElement(root.evalNode("databaseIdProvider"));
        // 解析  标签
        typeHandlerElement(root.evalNode("typeHandlers"));
        // 解析  标签
        mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
     
        throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
    }
}

解析之后parser.parse()最终反回了一个configuration对象 并交给了build重载方法
build(parser.parse())
SqlSessionFactory在这里被创建成功
public SqlSessionFactory build(Configuration config) {
     
    return new DefaultSqlSessionFactory(config);
}

SqlSessionFactoryBuilder().build(resourceAsStream)做了哪些事? 1,创建 XMLConfigBuilder解析核心配置文件中的所有内容并返回一个configuration
2,将这个configuration赋值给DefaultSqlSessionFactory中的Configuration对象属性
3,创建SqlSessionFactory实例

执行sql流程

// 创建一个sqlSession会话对象,用来实现与数据库的交互
SqlSession sqlSession = sqlSessionFactory.openSession();

sqlSessionFactory.openSession();做了什么

// 创建一个sqlSession会话对象,用来实现与数据库的交互
SqlSession sqlSession = sqlSessionFactory.openSession();

sqlSessionFactory.openSession();
public SqlSession openSession() {
     
    //第一个参数getDefaultExecutorType()返回的是执行器类型这里类型为SIMPLE
    //第二个参数是我们的事务隔离级别,这里赋值为null
    //第三个参数就是是否自动提交事务,我们这里默认不提交
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}

openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
     
    Transaction tx = null;
    try {
     
        // 获得 Environment 对象 运行环境对象
        final Environment environment = configuration.getEnvironment();
        // 创建 Transaction 对象 事务对象
        final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
        tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
        // 创建 Executor 对象 执行器对象在此被创建
        final Executor executor = configuration.newExecutor(tx, execType);
        // 返回一个sqlSession
        return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
     
        closeTransaction(tx); 
        throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
     
        ErrorContext.instance().reset();
    }
}

configuration.newExecutor(tx, execType);
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
     
    // 获得执行器类型 我们已经设定为SIMPLE
    executorType = executorType == null ? defaultExecutorType : executorType; 
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType; 
    // 创建对应实现的 Executor 对象
    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);
    }
    // 如果开启缓存,创建 CachingExecutor 对象,进行包装
    if (cacheEnabled) {
     
        executor = new CachingExecutor(executor);
    }
    // 应用插件 返回代理对象
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
}

sqlSessionFactory.openSession();做了什么
1、生成了类型为SIMPLE的执行器代理对象
2、创建了sqlSession,默认不自动提交事务

// 使用JDK动态代理对mapper接口产生代理对象
UserMapper mapper = sqlSession.getMapper(UserMapper.class);

sqlSession.getMapper(UserMapper.class);做了什么

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
     
    // 获得 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);
    }
}

mapperProxyFactory.newInstance(sqlSession);
 public T newInstance(SqlSession sqlSession) {
     
     // 创建了JDK动态代理的invocationHandler接口的实现类mapperProxy
     final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
     // 调用了重载方法返回代理对象
     return newInstance(mapperProxy);
 }

sqlSession.getMapper(UserMapper.class);做了什么
使用MapperProxyFactory根据jdk动态代理上产了mapper代理对象

//代理对象调用接口中的任意方法,执行的都是动态代理默认实现类MapperProxy的invoke方法
List<User> users = mapper.findAll();

调用查询方法时都做了什么

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 (isDefaultMethod(method)) {
     
            return invokeDefaultMethod(proxy, method, args);
        }
    } catch (Throwable t) {
     
        throw ExceptionUtil.unwrapThrowable(t);
    }
    // 获得 MapperMethod 对象
    final MapperMethod mapperMethod = cachedMapperMethod(method);
    // MapperMethod最终调用了执行的方法并返回执行结果
    return mapperMethod.execute(sqlSession, args);
}

mapperMethod.execute(sqlSession, args)
public Object execute(SqlSession sqlSession, Object[] args) {
     
    Object result;
    //判断mapper中的方法类型 我们是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:
            // 无返回,并且有 ResultHandler 方法参数,则将查询的结果,提交给 ResultHandler 进行处理
            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);
            // 执行查询,返回 Cursor
            } else if (method.returnsCursor()) {
     
                result = executeForCursor(sqlSession, args);
            // 执行查询,返回单个对象
            } else {
     
                // 转换参数
                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());
    }
    // 返回结果为 null ,并且返回类型为基本类型,则抛出 BindingException 异常
    if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
     
        throw new BindingException("Mapper method '" + command.getName()
                + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
    }
    // 返回结果
    return result;
}


executeForMany(sqlSession, args);
private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
     
    List<E> result;
    // 转换参数
    Object param = method.convertArgsToSqlCommandParam(args);
    // 执行 SELECT 操作
    if (method.hasRowBounds()) {
     
        RowBounds rowBounds = method.extractRowBounds(args);
        result = sqlSession.selectList(command.getName(), param, rowBounds);
    } else {
     
        result = sqlSession.selectList(command.getName(), param);
    }
    // 封装 Array 或 Collection 结果
    if (!method.getReturnType().isAssignableFrom(result.getClass())) {
     
        if (method.getReturnType().isArray()) {
      // 情况一,Array
            return convertToArray(result);
        } else {
     
            return convertToDeclaredCollection(sqlSession.getConfiguration(), result); // 情况二,Collection
        }
    }
    // 直接返回的结果
    return result; 
}

sqlSession.selectList(command.getName(), param);
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
     
    try {
     
        // 获得 MappedStatement 对象
        MappedStatement ms = configuration.getMappedStatement(statement);
        // 执行查询
        return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    } catch (Exception e) {
     
        throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
     
        ErrorContext.instance().reset();
    }
}
executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
     
    //根据传入的参数动态获得SQL语句,最后返回BoundSql
    BoundSql boundSql = ms.getBoundSql(parameter);
    //为本次查询创建缓存的Key
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
    // 调用重载方法查询
    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}

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());
    // 判断sqlSession是否关闭
    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 - 1
        queryStack--;
    }
    if (queryStack == 0) {
     
        // 执行延迟加载
        for (DeferredLoad deferredLoad : deferredLoads) {
     
            deferredLoad.load();
        }
        // 清空 deferredLoads
        deferredLoads.clear();
        // 如果缓存级别是 LocalCacheScope.STATEMENT ,则进行清理
        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);
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
     
    Statement stmt = null;
    try {
     
        // 拿到configuration对象
        Configuration configuration = ms.getConfiguration();
        // 传入参数创建StatementHanlder对象来执行查询
        StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
        // 参数?占位符处理
        stmt = prepareStatement(handler, ms.getStatementLog());
        // 调用StatementHandler.query方法进行读操作 并返回查询结果
        return handler.query(stmt, resultHandler);
    } finally {
     
        // 关闭 StatementHandler 对象
        closeStatement(stmt);
    }
}

prepareStatement(handler, ms.getStatementLog());
// 初始化 StatementHandler 对象
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
     
    Statement stmt;
    // 获得 Connection 对象
    Connection connection = getConnection(statementLog);
    // 创建 Statement 或 PrepareStatement 对象
    stmt = handler.prepare(connection, transaction.getTimeout());
    // 参数处理
    handler.parameterize(stmt);
    return stmt;
}
handler.parameterize(stmt);
public void setParameters(PreparedStatement ps) {
     
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
    // 遍历 ParameterMapping 数组
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings != null) {
     
        for (int i = 0; i < parameterMappings.size(); i++) {
     
            // 获得 ParameterMapping 对象
            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、jdbcType 属性
                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);
                }
            }
        }
    }
}


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

resultSetHandler.handleResultSets(ps);
public List<Object> handleResultSets(Statement stmt) throws SQLException {
     
    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());

    // 多 ResultSet 的结果集合
    final List<Object> multipleResults = new ArrayList<>();

    int resultSetCount = 0;
    // 获得首个 ResultSet 对象,并封装成 ResultSetWrapper 对象
    ResultSetWrapper rsw = getFirstResultSet(stmt);

    // 获得 ResultMap 数组
    // 在不考虑存储过程的多 ResultSet 的情况,普通的查询,实际就一个 ResultSet ,也就是说,resultMaps 就一个元素。
    List<ResultMap> resultMaps = mappedStatement.getResultMaps();
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount); // 校验
    while (rsw != null && resultMapCount > resultSetCount) {
     
        // 获得 ResultMap 对象
        ResultMap resultMap = resultMaps.get(resultSetCount);
        // 处理 ResultSet ,将结果添加到 multipleResults 中
        handleResultSet(rsw, resultMap, multipleResults, null);
        // 获得下一个 ResultSet 对象,并封装成 ResultSetWrapper 对象
        rsw = getNextResultSet(stmt);
        // 清理
        cleanUpAfterHandlingResultSet();
        // resultSetCount ++
        resultSetCount++;
    }

    String[] resultSets = mappedStatement.getResultSets();
    if (resultSets != null) {
     
        while (rsw != null && resultSetCount < resultSets.length) {
     
            ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
            if (parentMapping != null) {
     
                String nestedResultMapId = parentMapping.getNestedResultMapId();
                ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
                handleResultSet(rsw, resultMap, null, parentMapping);
            }
            rsw = getNextResultSet(stmt);
            cleanUpAfterHandlingResultSet();
            resultSetCount++;
        }
    }

    // 如果是 multipleResults 单元素,则取首元素返回结果
    return collapseSingleResultList(multipleResults);
}

调用查询方法时都做了什么
1、执行的动态代理默认实现类MapperProxy的invoke方法
2、invoke判断方法类型是查询方法
3、执行sqlSession中的select方法
4、executor执行查询方法
5、动态解析sql,创建查询的缓存key,
6、executor将查询操作交给statementHandler
7、statementhandler处理参数后查询将查询结果交给resultSetHandler
8、resultSetHandler处理结果后返回List

学习收货

1、通过mybaits流程分析梳理对近期学习内容进行了贯穿
2、更深层次的理解了mybatis主要构件
3、查询的方法具体怎样实现的sql查询以及结果集的封装

还是需要自己查看源代码学习,层层嵌套,博主整理能力有限

你可能感兴趣的:(mybatis源码学习,mybatis,业务分析,java,数据库,源码)