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);
        }
    }
}
相关推荐
Flobby52917 分钟前
Go语言新手村:轻松理解变量、常量和枚举用法
开发语言·后端·golang
Warren981 小时前
Java Stream流的使用
java·开发语言·windows·spring boot·后端·python·硬件工程
程序视点2 小时前
IObit Uninstaller Pro专业卸载,免激活版本,卸载清理注册表,彻底告别软件残留
前端·windows·后端
xidianhuihui2 小时前
go install报错: should be v0 or v1, not v2问题解决
开发语言·后端·golang
进击的铁甲小宝4 小时前
Django-environ 入门教程
后端·python·django·django-environ
掘金码甲哥4 小时前
Go动态感知资源变更的技术实践,你指定用过!
后端
王柏龙5 小时前
ASP.NET Core MVC中taghelper的ModelExpression详解
后端·asp.net·mvc
无限大65 小时前
算法精讲:二分查找(二)—— 变形技巧
后端
勇哥java实战分享5 小时前
基于 RuoYi-Vue-Pro 定制了一个后台管理系统 , 开源出来!
后端