Mybatis:简要架构

这里,从头梳理Mybatis一次数据库查询过程,首先通过SqlSession打开会话,使用会话获取到Mapper接口的代理对象,借助代理对象执行查询操作最终回到SqlSessionselectList方法,通过执行器Executor发起一次查询操作

public class DefaultSqlSession implements SqlSession {

    private final Executor executor;

    @Override
    public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
        try {
            MappedStatement ms = configuration.getMappedStatement(statement);
            // 通过executor发起一次查询操作
            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通过StatementHandler做进一步的操作

public class SimpleExecutor extends BaseExecutor {
    @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 handler = configuration.newStatementHandler(wrapper, 
                                    ms, parameter, rowBounds, resultHandler, boundSql);

            stmt = prepareStatement(handler, ms.getStatementLog());
            // 通过StatementHandler进行进一步的操作
            return handler.query(stmt, resultHandler);
        } finally {
            closeStatement(stmt);
        }
    }
}

StatementHandler中组装了ParameterHandlerResultSetHandler,前者用来填充PreparedStatementSQL语句中的?占位符,后者则用来处理查询数据库返回的ResultSet结果集

public abstract class BaseStatementHandler implements StatementHandler {

    protected final ResultSetHandler resultSetHandler;
    protected final ParameterHandler parameterHandler;

    protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, 
            Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler,
            BoundSql boundSql) {
        // ...
        // 创建ParameterHandler 
        this.parameterHandler = configuration
                .newParameterHandler(mappedStatement, parameterObject, boundSql);
        // 创建ResultSetHandler 
        this.resultSetHandler = configuration.newResultSetHandler(executor, 
                            mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
  }

如果当前使用PreparedStatement进行数据库查询,则会使用PreparedStatementHandler,它通过ParameterHandler接口的实现类DefaultParameterHandler为SQL语句填充占位符值

public class PreparedStatementHandler extends BaseStatementHandler {
   
    protected final ParameterHandler parameterHandler;

    public void parameterize(Statement statement) throws SQLException {
        // 通过ParameterHandler发起设置占位符值操作
        parameterHandler.setParameters((PreparedStatement) statement);
    }
}

DefaultParameterHandler通过TypeHandler为SQL占位符填充属性值

public class DefaultParameterHandler implements ParameterHandler {

    private final BoundSql boundSql;

    public void setParameters(PreparedStatement ps) {
        // ...
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        ParameterMapping parameterMapping = parameterMappings.get(i);
        TypeHandler typeHandler = parameterMapping.getTypeHandler();
        try {
            // 通过TypeHandler设置占位符
            typeHandler.setParameter(ps, i + 1, value, jdbcType);
        } catch (TypeException | SQLException e) {
        }
    }
}

最后使用ResultSetHandler处理返回结果集合,封装成需要的对象返回

public class SimpleStatementHandler extends BaseStatementHandler {

    protected final ResultSetHandler resultSetHandler;
    /**
     * 无论是查询一条记录或者多条记录,Mybatis统一使用查询多条记录的逻辑
     * 如果是多条记录会在SqlSession中获取集合第一个元素返回
     */
    public <E> List<E> query(Statement statement, ResultHandler resultHandler) 
            throws SQLException {
        String sql = boundSql.getSql();
        statement.execute(sql);
        // 通过ResultSetHandler处理结果集
        return resultSetHandler.handleResultSets(statement);
    }
}

综上所述,以下为Mybatis的简要架构图


Mybatis架构
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。