MyabtisPlus(8):启动后过程整合

494 阅读3分钟
  
DemoController->test():
    // ThreadLocal存储page对象,参考插件探究
    PageHelper.startPage(1, 10);
    QueryWrapper queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("id", 1);
    queryWrapper.eq("pid", 2);
    service.list(queryWrapper);
ServiceImpl->list():
    // 底层调用mapper方法
    return baseMapper.selectList(queryWrapper);
MybatisMapperProxy->invoke():
    // MybatisMapperMethod记录sql的类型、语句类型、参数等信息,参考参数值设置探究
    final MybatisMapperMethod mapperMethod = cachedMapperMethod(method);
    return mapperMethod.execute(sqlSession, args);
MybatisMapperMethod->execute():
    // 根据返回值的不同选择不同的方法
    else if (method.returnsMany()) {
        result = executeForMany(sqlSession, args);
    }
MybatisMapperMethod->executeForMany():
    // param要么是map类型,要么返回第一个参数
    Object param = method.convertArgsToSqlCommandParam(args);
    ......
    result = sqlSession.selectList(command.getName(), param);
SqlSessionTemplate->selectList():
    // sqlSessionProxy是一个代理类,参考启动阶段探究
    return this.sqlSessionProxy.selectList(statement, parameter);
SqlSessionTemplate->SqlSessionInterceptor->invoke():
    // 每次查询都是一个defaultSqlSession
    SqlSession sqlSession = getSqlSession(
        SqlSessionTemplate.this.sqlSessionFactory,
        SqlSessionTemplate.this.executorType,
        SqlSessionTemplate.this.exceptionTranslator);
        try {
            // 下面这条语句执行的是defaultSqlSession的selectList方法
            Object result = method.invoke(sqlSession, args);
        }
        ......
        // 释放连接,参考数据库连接池
        finally {
            if (sqlSession != null) {
              closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
            }
        }
DefaultSqlSession->selectList():
    return this.selectList(statement, parameter, RowBounds.DEFAULT);
DefaultSqlSession->selectList():
    MappedStatement ms = configuration.getMappedStatement(statement);
    return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
Plugin->invoke():
    // signatureMap的key是拦截器接口反射类,value是拦截的方法
    // 如果拦截的类和方法全都符合的话,就走拦截器的拦截方法
    Set methods = signatureMap.get(method.getDeclaringClass());
    if (methods != null && methods.contains(method)) {
        return interceptor.intercept(new Invocation(target, method, args));
    }
    // 否则走原来的方法,比如分页器拦截update方法时,就会走此
    return method.invoke(target, args);
// invocation,包含被代理类,被代理方法,方法参数信息
// 这一段的详细解释参考插件探究
PageInterceptor->intercept():
    ......
    // 根据sql源返回绑定sql对象,参考启动后动态SQL拼接探究
    boundSql = ms.getBoundSql(parameter);
    ......
    Long count = count(executor, ms, parameter, rowBounds, resultHandler, boundSql);    // --1
// 最终执行的是baseEcecutor的方法
BaseExecutor->query():  // --1
    list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
BaseExecutor->queryFromDatabase():
    list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
MybatisSimpleExecutor->doQuery():
    try {
        Configuration configuration = ms.getConfiguration();
        StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);   // --2
        // 底层最终调用con.prepareStatement(sql);ps.setString(1, "2");
        stmt = prepareStatement(handler, ms.getStatementLog(), false);  // --4
        return stmt == null ? Collections.emptyList() : handler.query(stmt, resultHandler);
    } finally {
        // 底层调用ps.close()
        closeStatement(stmt);
    }
RoutingStatementHandler->query():
    return delegate.query(statement, resultHandler);
PreparedStatementHandler->query():
    // 底层最终调用ps.executeQuery()方法
    ps.execute();
    // 可以看到传过来的resultHandler似乎并没有什么用
    // 使用结果集处理,返回list对象,执行rs.close(),这一段的详细过程参考ORM探究
    return resultSetHandler.handleResultSets(ps);
Configuration->newStatementHandler():   // --2
    // 实例化语句处理器,会包含参数处理器与结果集处理器
    StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);    // --3
    // 拦截器链有拦截语句处理器(PerformanceInterceptor),所以返回Plugin类
    statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler); 
    return statementHandler;
   
RoutingStatementHandler->RoutingStatementHandler(): // --3
    // 因为语句类型是预编译(带有?),所以实例化PreparedStatementHandler
    switch (ms.getStatementType()) {
        case STATEMENT:
            delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
            break;
        case PREPARED:
            delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
            break;
PreparedStatementHandler->BaseStatementHandler():
    // 调用的是父类的构造方法
    super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
BaseStatementHandler->BaseStatementHandler():
    /*实例化参数处理器,这边会根据拦截器链来看是否需要动态代理
    Configuration->newParameterHandler():ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement, parameterObject, boundSql);
    MybatisXMLLanguageDriver->createParameterHandler():return new MybatisDefaultParameterHandler(mappedStatement, parameterObject, boundSql);
    // processBatch包含了一段填充主键的过程,这边参考插入时主键策略探究
    MybatisDefaultParameterHandler->MybatisDefaultParameterHandler():super(mappedStatement, processBatch(mappedStatement, parameterObject), boundSql);
    */
    this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
    // 实例化结果集处理器,这边会根据拦截器链来看是否需要动态代理
    this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
MybatisSimpleExecutor->prepareStatement()   // --4
    // 从数据库连接池中获取一个连接
    Connection connection = getConnection(statementLog);
    // 设定了staticSql,参考JDBC探究最终拼接SQL探究
    stmt = handler.prepare(connection, transaction.getTimeout());
    if (stmt == null && !isCursor) {
        return null;
    } else {
        // 设定了bindValues,参考JDBC探究最终拼接SQL探究
        handler.parameterize(stmt);
        return stmt;
    }