MyBatis执行流程

MyBatis首先需要加载配置文件构建SqlSessionFactory,其次获取会话SqlSession,通过会话获取数据库操作映射对象执行数据库操作,最后才是关闭会话。可以看到,核心在于获取会话工厂和创建会话。

java 复制代码
public class MyBatisMain {
    // MyBatis启动执行操作
    // 1.加载全局配置文件
    // 2.加载映射文件
    // 3.配置内容存储Configuration
    public static void main(String[] args) {
        // 1. 获取配置文件
        InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
        // 2. 加载解析配置文件通过Builder对象建造SqlSessionFactory对象
        // 建造者模式: 构建复杂对象
        // (1) 完成配置文件加载解析
        // (2) 完成SqlSessionFactory创建
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        // 3. 根据SqlSessionFactory获取SqlSession对象
        SqlSession sqlSession = factory.openSession();
        // 4. 获取接口代码对象获得JDBC代理对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> list = mapper.selectUserList();
        for (User user : list) {
            System.out.println(user);
        }
        // 5. 关闭会话
        sqlSession.close();
    }
}

01 构建会话工厂

SqlSessionFactoryBuiler仅仅用来协助构建当前XML配置文件SqlSessionFactory对象,所以生命周期只存在于方法局部。

java 复制代码
public class SqlSessionFactoryBuilder {
    public SqlSessionFactory build(Reader reader) {
        return build(reader, null, null);
    }
    public SqlSessionFactory build(Reader reader, String environment) {
        return build(reader, environment, null);
    }
    public SqlSessionFactory build(Reader reader, Properties properties) {
        return build(reader, null, properties);
    }
    public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
        try {
            // XML配置文件构建者: 创建Configuration对象
            // MyBatis配置文件: mybatis-config.xml
            XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
            // 解析配置文件, 构建SqlSessionFactory
            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.
            }
        }
    }
    // 构建SqlSessionFactory
    public SqlSessionFactory build(Configuration config) {
        return new DefaultSqlSessionFactory(config);
    }
}

02 构建会话

java 复制代码
public class DefaultSqlSessionFactory implements SqlSessionFactory {
    private final Configuration configuration;

    public DefaultSqlSessionFactory(Configuration configuration) {
        this.configuration = configuration;
    }

    @Override
    public SqlSession openSession() {
        return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
    }

    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);
            // 根据事务工厂和执行器类型, 创建执行器
            final Executor executor = configuration.newExecutor(tx, execType);
            // 创建脚本会话
            return new DefaultSqlSession(configuration, executor, autoCommit);
        } catch (Exception e) {
            closeTransaction(tx);
            throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
        } finally {
            ErrorContext.instance().reset();
        }
    }

    private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) {
        // 事务工厂: 默认ManagedTransactionFactory
        if (environment == null || environment.getTransactionFactory() == null) {
            return new ManagedTransactionFactory();
        }
        return environment.getTransactionFactory();
    }

    private void closeTransaction(Transaction tx) {
        if (tx != null) {
            try {
                tx.close();
            } catch (SQLException ignore) {
                // Intentionally ignore. Prefer previous error.
            }
        }
    }
}

2.1 创建事务

java 复制代码
public class JdbcTransactionFactory implements TransactionFactory {
    @Override
    public Transaction newTransaction(Connection conn) {
        return new JdbcTransaction(conn);
    }
    @Override
    public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
        return new JdbcTransaction(ds, level, autoCommit);
    }
}

2.2 创建执行器

java 复制代码
public class Configuration {
    // 默认执行器类型
    protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
    // 插件
    protected final InterceptorChain interceptorChain = new InterceptorChain();

    public Configuration() {
        // 注册类型别名
        typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
        typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
    }
    
    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 {
            // 默认SimpleExecutor
            executor = new SimpleExecutor(this, transaction);
        }
        // 二级缓存开关, 默认cacheEnabled=true
        if (cacheEnabled) {
            executor = new CachingExecutor(executor);
        }
        // 植入插件逻辑, 至此四大对象已经全部拦截完毕
        executor = (Executor) interceptorChain.pluginAll(executor);
        return executor;
    }
}

03 获取映射对象

java 复制代码
public class DefaultSqlSession implements SqlSession {
    @Override
    public <T> T getMapper(Class<T> type) {
        return configuration.getMapper(type, this);
    }
}
public class Configuration {
    // 映射器注册中心
    protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
    
    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
        return mapperRegistry.getMapper(type, sqlSession);
    }
}

3.1 创建映射对象

java 复制代码
public class MapperRegistry {
    private final Configuration config;
    private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<>();

    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);
        }
    }
    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 {
                // 缓存映射器代理工厂: XMLMapperBuilder#bindMapperForNamespace
                knownMappers.put(type, new MapperProxyFactory<>(type));
                
                // 解析映射器所有方法, 如@Select
                MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
                parser.parse();
                loadCompleted = true;
            } finally {
                if (!loadCompleted) {
                    knownMappers.remove(type);
                }
            }
        }
    }
    public <T> boolean hasMapper(Class<T> type) {
        return knownMappers.containsKey(type);
    }
}

3.2 映射代理工厂

java 复制代码
public class MapperProxyFactory<T> {
    // 映射器接口
    private final Class<T> mapperInterface;
    // 映射器方法调用者缓存
    private final Map<Method, MapperMethodInvoker> methodCache = new ConcurrentHashMap<>();

    public MapperProxyFactory(Class<T> mapperInterface) {
        this.mapperInterface = mapperInterface;
    }

    @SuppressWarnings("unchecked")
    // 创建映射器接口代理对象
    protected T newInstance(MapperProxy<T> mapperProxy) {
        // 1.类加载器
        // 2.被代理类实现接口
        // 3.实现InvocationHandler调用类
        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);
    }
}

04 查询方法调用

java 复制代码
public class MapperProxy<T> implements InvocationHandler, Serializable {
    // 允许方法
    private static final int ALLOWED_MODES = MethodHandles.Lookup.PRIVATE | 
        MethodHandles.Lookup.PROTECTED |
        MethodHandles.Lookup.PACKAGE |
        MethodHandles.Lookup.PUBLIC;
    // 构造器
    private static final Constructor<Lookup> lookupConstructor;
    // 私有方法
    private static final Method privateLookupInMethod;
    // 会话
    private final SqlSession sqlSession;
    // 映射器类
    private final Class<T> mapperInterface;
    // 方法调用缓存
    private final Map<Method, MapperMethodInvoker> methodCache;

    @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);
            }
            return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
        } catch (Throwable t) {
            throw ExceptionUtil.unwrapThrowable(t);
        }
    }
     private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {
        try {
            return methodCache.computeIfAbsent(method, m -> {
                // 接口默认方法: default申明方法, 直接调用
                if (m.isDefault()) {
                    try {
                        // java8
                        if (privateLookupInMethod == null) {
                            return new DefaultMethodInvoker(getMethodHandleJava8(method));
                        }
                        // java9
                        return new DefaultMethodInvoker(getMethodHandleJava9(method));
                    } catch (IllegalAccessException | InstantiationException | InvocationTargetException | NoSuchMethodException e) {
                        throw new RuntimeException(e);
                    }
                }
                // 创建MapperMethod
                return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
            });
        } catch (RuntimeException re) {
            Throwable cause = re.getCause();
            throw cause == null ? re : cause;
        }
    }
    
    private MethodHandle getMethodHandleJava8(Method method) throws IllegalAccessException, InstantiationException, InvocationTargetException {
        final Class<?> declaringClass = method.getDeclaringClass();
        return lookupConstructor.newInstance(declaringClass, ALLOWED_MODES).unreflectSpecial(method, declaringClass);
    }
    private MethodHandle getMethodHandleJava9(Method method) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        final Class<?> declaringClass = method.getDeclaringClass();
        // 找到目标方法
        return ((Lookup) privateLookupInMethod.invoke(null, declaringClass, MethodHandles.lookup()))
        .findSpecial(declaringClass, method.getName(), MethodType.methodType(method.getReturnType(), method.getParameterTypes()), declaringClass);
    }
}
java 复制代码
public class MapperProxy<T> implements InvocationHandler, Serializable {
    interface MapperMethodInvoker {
        Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable;
    }

    private static class PlainMethodInvoker implements MapperMethodInvoker {
        private final MapperMethod mapperMethod;
        public PlainMethodInvoker(MapperMethod mapperMethod) {
            super();
            this.mapperMethod = mapperMethod;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
            // SQL执行真正起点
            return mapperMethod.execute(sqlSession, args);
        }
    }

    private static class DefaultMethodInvoker implements MapperMethodInvoker {
        private final MethodHandle methodHandle;
        public DefaultMethodInvoker(MethodHandle methodHandle) {
            super();
            this.methodHandle = methodHandle;
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
            // 带参调用
            return methodHandle.bindTo(proxy).invokeWithArguments(args);
        }
    }}
}

4.1 映射方法

java 复制代码
public class MapperMethod {
    // SQL命令, 如statementId=com.feiyu.mapper.BlogMapper.selectById
    private final SqlCommand command;
    // 方法签名, 主要读取返回值类型
    private final MethodSignature method;

    public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
        this.command = new SqlCommand(config, mapperInterface, method);
        this.method = new MethodSignature(config, mapperInterface, method);
    }

    public Object execute(SqlSession sqlSession, Object[] args) {
        Object result;
        // SQL脚本类型
        switch (command.getType()) {
            case INSERT: {
                // ParamNameResolver处理实参与指定参数名关联
                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;
                } 
                // 返回List类型数据
                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 {
                    // 返回单一对象方法
                    Object param = method.convertArgsToSqlCommandParam(args);
                    // 普通select语句执行入口
                    result = sqlSession.selectOne(command.getName(), param);
                    // 返回值类型为Optional
                    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;
    }
}

4.2 查询列表

java 复制代码
public class MapperMethod {
    // SQL命令, 如statementId=com.feiyu.mapper.BlogMapper.selectById
    private final SqlCommand command;
    // 方法签名, 主要读取返回值类型
    private final MethodSignature method;

    private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
        List<E> result;
        // 参数转化
        Object param = method.convertArgsToSqlCommandParam(args);
        if (method.hasRowBounds()) {
            RowBounds rowBounds = method.extractRowBounds(args);
            // 再次调用会话拆线呢
            result = sqlSession.selectList(command.getName(), param, rowBounds);
        } else {
            result = sqlSession.selectList(command.getName(), param);
        }
        // issue #510 Collections & arrays support
        if (!method.getReturnType().isAssignableFrom(result.getClass())) {
            // 数组
            if (method.getReturnType().isArray()) {
                return convertToArray(result);
            }
            // 集合类
            return convertToDeclaredCollection(sqlSession.getConfiguration(), result);
        }
        return result;
    }
    
    private <E> Object convertToArray(List<E> list) {
        Class<?> arrayComponentType = method.getReturnType().getComponentType();
        Object array = Array.newInstance(arrayComponentType, list.size());
        // 基础类型
        if (arrayComponentType.isPrimitive()) {
            // 基本类型包装类型
            for (int i = 0; i < list.size(); i++) {
                Array.set(array, i, list.get(i));
            }
            return array;
        } else {
            return list.toArray((E[]) array);
        }
    }
    
    private <E> Object convertToDeclaredCollection(Configuration config, List<E> list) {
        // 通过ObjectFactory创建对象反射方式
        Object collection = config.getObjectFactory().create(method.getReturnType());
        // 创建MetaObject对象
        MetaObject metaObject = config.newMetaObject(collection);
        metaObject.addAll(list);
        return collection;
    }
}

05 会话执行查询

java 复制代码
public class DefaultSqlSession implements SqlSession {
    @Override
    public <E> List<E> selectList(String statement) {
        return this.selectList(statement, null);
    }
    @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 {
            // 获取映射语句
            MappedStatement ms = configuration.getMappedStatement(statement);
            // 如果开启二级缓存, Executor会被CachingExecutor装饰
            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();
        }
    }
    
    private Object wrapCollection(final Object object) {
        // 集合类型
        if (object instanceof Collection) {
            StrictMap<Object> map = new StrictMap<>();
            map.put("collection", object);
            if (object instanceof List) {
                map.put("list", object);
            }
            return map;
        }
        // 数组类型
        if (object != null && object.getClass().isArray()) {
            StrictMap<Object> map = new StrictMap<>();
            map.put("array", object);
            return map;
        }
        return object;
    }
}

5.1 基础执行器

java 复制代码
public abstract class BaseExecutor implements Executor {
    // 事务
    protected Transaction transaction;
    // 执行器
    protected Executor wrapper;

    protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
    // 结果处理器缓存
    protected PerpetualCache localCache;
    // 输入参数缓存
    protected PerpetualCache localOutputParameterCache;
    // 全局配置
    protected Configuration configuration;

    // 查询栈深度
    protected int queryStack;
    // 是否已关闭
    private boolean closed;
    
    @Override
    public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
        BoundSql boundSql = ms.getBoundSql(parameter);
        // 创建缓存键: 一级缓存和二级缓存是同一个
        CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
        return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
    }
    @Override
    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.");
        }
        // flushCache=true: 强制清空缓存
        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();
            // 缓存级别: Statement
            if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
                // issue #482
                clearLocalCache();
            }
        }
        return list;
    }
    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;
    }
    // 扩展点: 执行查询
    protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException;
}

5.2 简单执行器

java 复制代码
public class SimpleExecutor extends BaseExecutor {
    public SimpleExecutor(Configuration configuration, Transaction transaction) {
        super(configuration, transaction);
    }
    @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();
            // SQL处理关键对象StatementHandler
            StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
            // 获取Statement对象
            stmt = prepareStatement(handler, ms.getStatementLog());
            // 执行查询
            return handler.query(stmt, resultHandler);
        } finally {
            // 用完就关闭
            closeStatement(stmt);
        }
    }
    
    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
        Statement stmt;
        // 获取数据库链接
        Connection connection = getConnection(statementLog);
        // 获取Statement对象
        stmt = handler.prepare(connection, transaction.getTimeout());
        // 处理动态参数
        handler.parameterize(stmt);
        return stmt;
    }
}

05 语句处理

java 复制代码
public class RoutingStatementHandler implements StatementHandler {
    // 封装真正StatementHandler对象
    private final StatementHandler delegate;

    public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
        // StatementType根据增删改查标签statementType="PREPARED"配置, 默认值PREPARED
        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;
            case CALLABLE:
                delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
                break;
            default:
                throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
        }
    }

    @Override
    public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
        return delegate.prepare(connection, transactionTimeout);
    }

    @Override
    public void parameterize(Statement statement) throws SQLException {
        delegate.parameterize(statement);
    }

    @Override
    public void batch(Statement statement) throws SQLException {
        delegate.batch(statement);
    }

    @Override
    public int update(Statement statement) throws SQLException {
        return delegate.update(statement);
    }

    @Override
    public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
        return delegate.query(statement, resultHandler);
    }

    @Override
    public <E> Cursor<E> queryCursor(Statement statement) throws SQLException {
        return delegate.queryCursor(statement);
    }

    @Override
    public BoundSql getBoundSql() {
        return delegate.getBoundSql();
    }

    @Override
    public ParameterHandler getParameterHandler() {
        return delegate.getParameterHandler();
    }
}

5.1 PreparedStatementHandler

java 复制代码
public class PreparedStatementHandler extends BaseStatementHandler {
	public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
		super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
	}

	@Override
	public void batch(Statement statement) throws SQLException {
		PreparedStatement ps = (PreparedStatement) statement;
		// 添加到批处理
		ps.addBatch();
	}

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

    // 处理参数
	@Override
    public void parameterize(Statement statement) throws SQLException {
        parameterHandler.setParameters((PreparedStatement) statement);
    }
}

5.2 结果处理

java 复制代码
public class DefaultResultSetHandler implements ResultSetHandler {
    // 支持结果集类型: Statement、PreparedStatement和CallableStatement,
    // 其中CallableStatement存储过程可能返回多个ResultSet对象
    @Override
    public List<Object> handleResultSets(Statement stmt) throws SQLException {
        ErrorContext.instance().activity("handling results").object(mappedStatement.getId());

        // 保存映射结果集对象
        final List<Object> multipleResults = new ArrayList<>();

        // 结果集数量
        int resultSetCount = 0;
        // 获取第一个ResultSet对象
        ResultSetWrapper rsw = getFirstResultSet(stmt);
        
        // 如果SQL能够产生多个ResultSet, 那么resultMap可以配置多个<resultMap>, 实现对多个结果集映射
        List<ResultMap> resultMaps = mappedStatement.getResultMaps();
        // 获取resultMap个数
        int resultMapCount = resultMaps.size();
        // 如果结果集不为空, 那么resultMaps不能为空, 否则抛异常
        validateResultMapsCount(rsw, resultMapCount);
        // 遍历resultMaps集合
        while (rsw != null && resultMapCount > resultSetCount) {
            // 获取循环ResultMap对象
            ResultMap resultMap = resultMaps.get(resultSetCount);
            // 处理单个ResultSet对象, 也就是根据resultMap定义规则映射ResultSet
            // 并将单个结果映射添加到multipleResults
            handleResultSet(rsw, resultMap, multipleResults, null);
            rsw = getNextResultSet(stmt);// 获取下一个结果集
            cleanUpAfterHandlingResultSet(); // 清空nestedResultObjects
            resultSetCount++;
        }

        // resultSets仅对多结果集情况适用, 语句执行后返回结果集逗号分隔名称
        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++;
            }
        }

        return collapseSingleResultList(multipleResults);
    }
    // 获取第一个ResultSet对象
    private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
        ResultSet rs = stmt.getResultSet(); // 获取ResultSet对象
        while (rs == null) {
            if (stmt.getMoreResults()) { // 检测是否有待处理ResultSet
                rs = stmt.getResultSet();
            } else {
                if (stmt.getUpdateCount() == -1) { // 没有待处理ResultSet对象
                    break;
                }
            }
        }
        // 结果集封装为ResultSetWrapper对象
        return rs != null ? new ResultSetWrapper(rs, configuration) : null;
    }
    // 如果结果集不为空, 那么resultMaps不能为空, 否则抛异常
    private void validateResultMapsCount(ResultSetWrapper rsw, int resultMapCount) {
        if (rsw != null && resultMapCount < 1) {
            throw new ExecutorException("A query was run and no Result Maps were found for the Mapped Statement '" + mappedStatement.getId() + "'.  It's likely that neither a Result Type nor a Result Map was specified.");
        }
    }
    // 映射单个结果集
    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) { 
                    // 如果用户没有指定处理映射结果ResultHandler对象, 则使用默认的
                    DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
                    // 映射ResultSet结果添加到DefaultResultHandler暂存
                    handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
                    // DefaultResultHandler保存结果添加到multipleResults对象
                    multipleResults.add(defaultResultHandler.getResultList());
                } else {
                    handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
                }
            }
        } finally {
            // issue #228 (close resultsets) resultSet.close()
            closeResultSet(rsw.getResultSet());
        }
    }
    public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
        if (resultMap.hasNestedResultMaps()) { // 处理嵌套映射
            ensureNoRowBounds();
            checkResultHandler();
            handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
        } else {// 处理简单映射
            handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
        }
    }
    private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException {
        DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
        ResultSet resultSet = rsw.getResultSet();
        skipRows(resultSet, rowBounds); // 根据offset定位到指定位置
        // 检测引进处理行数是否已经达到了上限(RowBounds.limit), 以及是否还有待处理记录
        while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) {
            // 获取映射对象ResultMap
            ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
            // 根据ResultMap处理ResultSet结果集
            Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
            // 保存映射得到结果对象
            storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
        }
    }
}
相关推荐
长栎1 小时前
写 for 循环写了十年,你却从没用过迭代器模式最狠的那一面
后端
LiaCode1 小时前
Redis 在生产项目的使用
前端·后端
用户559822481221 小时前
Docker Compose Down 导致容器数据误删——ext4 日志恢复全记录
后端
LiaCode1 小时前
一天学完 redis 的爽翻版核心知识总结
前端·后端
大刚测试开发实战1 小时前
如何内网穿透访问本地私有化部署的TestHub
前端·后端·github
xiaodaoluanzha1 小时前
迄今為止,最簡單的編程語言 Nolang
前端·后端
Csvn1 小时前
Docker 容器管理入门 — 从镜像到容器编排
后端
用户762352425911 小时前
ShardingJDBC
后端
行者全栈架构师1 小时前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端
Colin草率地做慢慢地改1 小时前
关于QuickStore这个项目的重构(2)- 数据库建表文件
后端·面试·架构