
MyBatis SqlSession创建全链路解析从工厂构建到执行器选择的深度剖析「MyBatis SqlSession诞生记SqlSessionFactoryBuilder构建流程Executor选择策略事务管理初始化全揭秘」SqlSessionFactoryBuilderMyBatis框架的启动引擎在MyBatis的整体架构中SqlSessionFactoryBuilder扮演着框架启动器的关键角色。它不仅仅是配置文件的解析器更是整个MyBatis运行时环境的构建者。理解其工作机理是掌握MyBatis框架运行机制的重要基础。目录MyBatis SqlSession创建全链路解析从工厂构建到执行器选择的深度剖析SqlSessionFactoryBuilderMyBatis框架的启动引擎build()方法的完整执行链路构建过程的层次化分析错误处理与上下文管理DefaultSqlSessionFactorySqlSession的制造工厂openSession方法族的多维度支持openSessionFromDataSource核心创建逻辑深度解析事务管理器的初始化时机与策略事务工厂的选择机制事务实例的创建过程分析连接获取与事务属性设置Executor类型的选择策略与执行机制Executor体系的架构设计各种Executor的性能特性对比SimpleExecutor标准执行器ReuseExecutor语句重用执行器BatchExecutor批量处理执行器CachingExecutor缓存装饰器模式应用插件机制在SqlSession创建中的增强作用拦截器链的构建与执行典型插件的执行时机分析性能优化与实践建议Executor选择的性能影响事务配置的最佳实践连接池参数调优总结与展望(❁´◡❁)您的点赞➕评论➕收藏⭐是作者创作的最大动力 支持我点赞收藏⭐️留言欢迎留言讨论我们常常在当下感到时间慢觉得未来遥远但一旦回头看时间已经悄然流逝。对于未来尽管如此也应该保持一种从容的态度相信未来仍有许多可能性等待着我们。build()方法的完整执行链路构建过程的层次化分析SqlSessionFactoryBuilder.build()方法采用了典型的建造者模式将复杂的构建过程封装在简洁的API之后public class SqlSessionFactoryBuilder { // 核心构建方法 - 承载多种重载版本的统一入口 public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) { try { // 阶段1配置解析器初始化 XMLConfigBuilder parser new XMLConfigBuilder(inputStream, environment, properties); // 阶段2配置对象构建 Configuration config parser.parse(); // 阶段3SqlSessionFactory实例化 return build(config); } catch (Exception e) { // 异常处理与资源清理 throw ExceptionFactory.wrapException(Error building SqlSession., e); } finally { ErrorContext.instance().reset(); closeInputStream(inputStream); } } }错误处理与上下文管理MyBatis在构建过程中采用了精细的错误处理机制// ErrorContext采用ThreadLocal实现线程安全的错误上下文管理 public class ErrorContext { private static final ThreadLocalErrorContext LOCAL new ThreadLocal(); private String resource; private String activity; private String object; private String message; private String sql; private Throwable cause; public static ErrorContext instance() { ErrorContext context LOCAL.get(); if (context null) { context new ErrorContext(); LOCAL.set(context); } return context; } }这种设计确保了在多线程环境下每个线程都能拥有独立的错误上下文便于问题定位和诊断。DefaultSqlSessionFactorySqlSession的制造工厂openSession方法族的多维度支持DefaultSqlSessionFactory通过方法重载提供了灵活的SqlSession创建选项满足不同场景的需求public class DefaultSqlSessionFactory implements SqlSessionFactory { private final Configuration configuration; // 基础版本 - 使用默认配置 Override public SqlSession openSession() { return openSessionFromDataSource( configuration.getDefaultExecutorType(), null, false ); } // 自动提交控制版本 Override public SqlSession openSession(boolean autoCommit) { return openSessionFromDataSource( configuration.getDefaultExecutorType(), null, autoCommit ); } // 事务隔离级别指定版本 Override public SqlSession openSession(TransactionIsolationLevel level) { return openSessionFromDataSource( configuration.getDefaultExecutorType(), level, false ); } // 执行器类型指定版本 Override public SqlSession openSession(ExecutorType execType) { return openSessionFromDataSource(execType, null, false); } // 连接参数指定版本 Override public SqlSession openSession(Connection conn) { return openSessionFromConnection(configuration.getDefaultExecutorType(), conn); } }openSessionFromDataSource核心创建逻辑深度解析这是SqlSession创建过程中最核心的方法包含了事务初始化、执行器选择等关键决策private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx null; try { // 步骤1环境配置获取 final Environment environment configuration.getEnvironment(); if (environment null) { throw new ConfigurationException(Environment is required.); } // 步骤2事务工厂实例化 final TransactionFactory transactionFactory getTransactionFactoryFromEnvironment(environment); // 步骤3事务对象创建关键时机点 tx transactionFactory.newTransaction( environment.getDataSource(), level, autoCommit ); // 步骤4执行器创建与装饰 final Executor executor configuration.newExecutor(tx, execType); // 步骤5SqlSession实例化 return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { // 异常处理关闭已创建的事务 closeTransaction(tx); throw ExceptionFactory.wrapException(Error opening session. Cause: e, e); } }事务管理器的初始化时机与策略事务工厂的选择机制事务管理器的初始化发生在SqlSession创建流程的早期阶段这体现了MyBatis对数据一致性的重视private TransactionFactory getTransactionFactoryFromEnvironment(Environment environment) { // 环境未配置时的默认策略 if (environment null || environment.getTransactionFactory() null) { if (log.isDebugEnabled()) { log.debug(Using default transaction factory: ManagedTransactionFactory); } return new ManagedTransactionFactory(); } // 返回配置的事务工厂 if (log.isDebugEnabled()) { log.debug(Using configured transaction factory: environment.getTransactionFactory().getClass().getSimpleName()); } return environment.getTransactionFactory(); }事务实例的创建过程分析不同的事务工厂创建不同类型的事务管理器// JDBC事务工厂实现 public class JdbcTransactionFactory implements TransactionFactory { Override public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) { if (log.isDebugEnabled()) { log.debug(Creating new JDBC transaction with autoCommit: autoCommit); } return new JdbcTransaction(ds, level, autoCommit); } } // 托管事务工厂实现 public class ManagedTransactionFactory implements TransactionFactory { Override public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) { if (log.isDebugEnabled()) { log.debug(Creating new Managed transaction); } return new ManagedTransaction(ds, level, autoCommit); } }连接获取与事务属性设置事务管理器在初始化时会立即获取数据库连接并设置事务属性public class JdbcTransaction implements Transaction { protected void openConnection() throws SQLException { if (log.isDebugEnabled()) { log.debug(Opening JDBC Connection); } // 获取数据库连接 connection dataSource.getConnection(); // 设置事务隔离级别如果指定 if (level ! null) { int currentLevel connection.getTransactionIsolation(); if (currentLevel ! level.getLevel()) { if (log.isDebugEnabled()) { log.debug(Changing transaction isolation level from currentLevel to level.getLevel()); } connection.setTransactionIsolation(level.getLevel()); } } // 设置自动提交模式 setDesiredAutoCommit(autoCommit); } private void setDesiredAutoCommit(boolean desiredAutoCommit) { boolean currentAutoCommit connection.getAutoCommit(); if (currentAutoCommit ! desiredAutoCommit) { if (log.isDebugEnabled()) { log.debug(Changing autocommit from currentAutoCommit to desiredAutoCommit); } connection.setAutoCommit(desiredAutoCommit); } } }Executor类型的选择策略与执行机制Executor体系的架构设计MyBatis设计了灵活的Executor体系通过配置化的方式支持不同的执行策略public class Configuration { // 执行器创建的核心方法 public Executor newExecutor(Transaction transaction, ExecutorType executorType) { // 执行器类型推断逻辑 executorType executorType null ? defaultExecutorType : executorType; executorType executorType null ? ExecutorType.SIMPLE : executorType; Executor executor; // 基于类型的执行器实例化 if (log.isDebugEnabled()) { log.debug(Creating executor of type: executorType); } switch (executorType) { case BATCH: executor new BatchExecutor(this, transaction); break; case REUSE: executor new ReuseExecutor(this, transaction); break; default: executor new SimpleExecutor(this, transaction); } // 二级缓存装饰如果启用 if (cacheEnabled) { if (log.isDebugEnabled()) { log.debug(Enabling cache for executor); } executor new CachingExecutor(executor); } // 插件机制增强 executor (Executor) interceptorChain.pluginAll(executor); return executor; } }各种Executor的性能特性对比SimpleExecutor标准执行器public class SimpleExecutor extends BaseExecutor { Override public E ListE 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( this, ms, parameter, rowBounds, resultHandler, boundSql); // 每次执行都创建新的PreparedStatement stmt prepareStatement(handler); return handler.query(stmt, resultHandler); } finally { // 执行完成后立即关闭Statement closeStatement(stmt); } } }适用场景通用查询场景内存敏感环境ReuseExecutor语句重用执行器public class ReuseExecutor extends BaseExecutor { // 重用相同SQL的PreparedStatement private final MapString, PreparedStatement statementMap new HashMap(); Override public E ListE doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { Configuration configuration ms.getConfiguration(); StatementHandler handler configuration.newStatementHandler( this, ms, parameter, rowBounds, resultHandler, boundSql); String sql boundSql.getSql(); PreparedStatement stmt; // 检查是否已存在相同SQL的PreparedStatement if (hasStatementFor(sql)) { if (log.isDebugEnabled()) { log.debug(Reusing prepared statement for SQL: sql); } stmt getStatement(sql); } else { // 创建新的PreparedStatement并缓存 stmt prepareNewStatement(handler, sql); } handler.parameterize(stmt); return handler.query(stmt, resultHandler); } }适用场景相同SQL频繁执行的OLTP系统BatchExecutor批量处理执行器public class BatchExecutor extends BaseExecutor { private final ListStatement statementList new ArrayList(); private final ListBatchResult batchResultList new ArrayList(); private String currentSql; private MappedStatement currentStatement; Override public int doUpdate(MappedStatement ms, Object parameter) throws SQLException { // 批量操作逻辑 if (isSameBatch(ms, parameter)) { // 添加到当前批次 addToCurrentBatch(ms, parameter); return BATCH_UPDATE_RETURN_VALUE; } else { // 执行当前批次并开始新批次 executeBatch(); startNewBatch(ms, parameter); return BATCH_UPDATE_RETURN_VALUE; } } Override public void commit(boolean required) throws SQLException { // 提交时执行所有批量操作 executeBatch(); super.commit(required); } }适用场景大数据量批量插入、更新操作CachingExecutor缓存装饰器模式应用通过装饰器模式为执行器添加二级缓存功能体现了开闭原则的优雅应用public class CachingExecutor implements Executor { private final Executor delegate; private final TransactionalCacheManager tcm new TransactionalCacheManager(); Override public E ListE query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { // 检查是否启用缓存 Cache cache ms.getCache(); if (cache null) { return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); } // 缓存刷新检查 flushCacheIfRequired(ms); // 缓存查询逻辑 if (ms.isUseCache() resultHandler null) { ensureNoOutParams(ms, boundSql); SuppressWarnings(unchecked) ListE list (ListE) tcm.getObject(cache, key); if (list null) { // 缓存未命中委托给底层执行器查询 list delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); // 将结果放入缓存 tcm.putObject(cache, key, list); } else { if (log.isDebugEnabled()) { log.debug(Cache hit for key: key); } } return list; } return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql); } }插件机制在SqlSession创建中的增强作用拦截器链的构建与执行MyBatis通过责任链模式实现插件机制在SqlSession创建过程中对Executor进行增强public class InterceptorChain { private final ListInterceptor interceptors new ArrayList(); public Object pluginAll(Object target) { // 按顺序应用所有拦截器 for (Interceptor interceptor : interceptors) { if (log.isDebugEnabled()) { log.debug(Applying interceptor: interceptor.getClass().getSimpleName()); } target interceptor.plugin(target); } return target; } }典型插件的执行时机分析以分页插件为例观察其在SqlSession创建过程中的介入时机Intercepts({ Signature(type Executor.class, method query, args {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}) }) public class PageInterceptor implements Interceptor { Override public Object intercept(Invocation invocation) throws Throwable { // 在Executor.query方法执行前后进行拦截 Object[] args invocation.getArgs(); MappedStatement ms (MappedStatement) args[0]; Object parameter args[1]; RowBounds rowBounds (RowBounds) args[2]; // 分页逻辑处理 if (shouldPage(rowBounds)) { return handlePagedQuery(invocation, ms, parameter, rowBounds); } // 继续执行原始逻辑 return invocation.proceed(); } }性能优化与实践建议Executor选择的性能影响根据实际业务场景选择合适的Executor类型SIMPLE执行器优点内存占用小无状态缺点频繁创建/销毁PreparedStatement适用查询多样性高的场景REUSE执行器优点减少PreparedStatement创建开销缺点内存占用较高需要维护Statement缓存适用SQL模板化程度高的OLTP系统BATCH执行器优点批量操作性能极佳缺点编程模型复杂内存占用大适用数据导入、批量更新场景事务配置的最佳实践!-- 生产环境推荐配置 -- transactionManager typeJDBC property nameautoCommit valuefalse/ /transactionManager !-- 开发环境便捷配置 -- transactionManager typeJDBC property nameautoCommit valuetrue/ /transactionManager连接池参数调优dataSource typePOOLED !-- 根据并发量调整连接数 -- property namepoolMaximumActiveConnections value50/ property namepoolMaximumIdleConnections value10/ property namepoolMaximumCheckoutTime value20000/ !-- 根据网络状况调整超时时间 -- property namepoolTimeToWait value20000/ !-- 连接有效性检查 -- property namepoolPingEnabled valuetrue/ property namepoolPingQuery valueSELECT 1/ property namepoolPingConnectionsNotUsedFor value3600000/ /dataSource总结与展望SqlSession的创建过程是MyBatis框架初始化的核心环节它完美体现了框架在设计上的诸多考量灵活性设计通过多种openSession重载方法支持不同使用场景性能优化提供多种Executor实现满足不同性能需求扩展性支持通过插件机制允许功能增强资源管理完善的事务和连接生命周期管理深入理解这一过程不仅有助于我们更好地使用MyBatis更能从中学习到优秀框架的设计思想和实现技巧为我们的技术成长提供宝贵的参考。(❁´◡❁)您的点赞➕评论➕收藏⭐是作者创作的最大动力 支持我点赞收藏⭐️留言欢迎留言讨论
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。