图示 發表於 2025-9-25 08:31:00

【源码解读之 Mybatis】【基础篇】-- 第3篇:SqlSession的创建与生命周期

<h1 id="第3篇sqlsession的创建与生命周期">第3篇:SqlSession的创建与生命周期</h1>
<h2 id="1-学习目标确认">1. 学习目标确认</h2>
<h3 id="10-第2篇思考题解答">1.0 第2篇思考题解答</h3>
<p>在深入学习SqlSession之前,让我们先回顾并解答第2篇中提出的思考题,这将帮助我们更好地理解SqlSession在整个架构中的作用。</p>
<h4 id="思考题1为什么mybatis要设计如此复杂的配置系统">思考题1:为什么MyBatis要设计如此复杂的配置系统?</h4>
<p><strong>答案要点</strong>:</p>
<ul>
<li><strong>统一管理</strong>:所有配置项集中管理,避免配置分散和重复</li>
<li><strong>灵活性</strong>:支持XML、注解、代码三种配置方式,满足不同场景需求</li>
<li><strong>可扩展性</strong>:通过插件系统和自定义配置支持功能扩展</li>
<li><strong>性能优化</strong>:配置缓存、懒加载等机制提升性能</li>
<li><strong>类型安全</strong>:强类型配置减少运行时错误</li>
</ul>
<p><strong>SqlSession的作用</strong>:SqlSession作为配置系统的使用者,通过Configuration获取所有必要的配置信息。</p>
<h4 id="思考题2配置系统的扩展性体现在哪些方面">思考题2:配置系统的扩展性体现在哪些方面?</h4>
<p><strong>答案要点</strong>:</p>
<ul>
<li><strong>插件扩展</strong>:Interceptor接口支持功能扩展</li>
<li><strong>类型处理器扩展</strong>:TypeHandler接口支持自定义类型转换</li>
<li><strong>对象工厂扩展</strong>:ObjectFactory接口支持自定义对象创建</li>
<li><strong>数据源扩展</strong>:DataSource接口支持自定义数据源</li>
<li><strong>事务管理扩展</strong>:TransactionFactory接口支持自定义事务管理</li>
</ul>
<p><strong>SqlSession的扩展性</strong>:SqlSession通过Executor、StatementHandler等组件实现功能扩展。</p>
<h4 id="思考题3如何优化配置解析的性能">思考题3:如何优化配置解析的性能?</h4>
<p><strong>答案要点</strong>:</p>
<ul>
<li><strong>缓存机制</strong>:解析后的配置对象缓存,避免重复解析</li>
<li><strong>懒加载</strong>:非必需配置延迟加载,减少启动时间</li>
<li><strong>批量处理</strong>:相关配置项批量解析,提高效率</li>
<li><strong>内存优化</strong>:优化配置对象的内存使用,减少GC压力</li>
</ul>
<p><strong>SqlSession的性能</strong>:SqlSession通过Executor缓存、连接池等技术优化性能。</p>
<h4 id="思考题4基于配置系统的理解应该从哪个组件开始深入源码分析">思考题4:基于配置系统的理解,应该从哪个组件开始深入源码分析?</h4>
<p><strong>推荐顺序</strong>:SqlSession → Executor → StatementHandler → ParameterHandler + ResultSetHandler</p>
<p><strong>从SqlSession开始的原因</strong>:</p>
<ul>
<li>SqlSession是配置系统的直接使用者</li>
<li>理解SqlSession有助于理解整个执行流程</li>
<li>为后续学习Executor等组件奠定基础</li>
</ul>
<h3 id="11-sqlsession概述基于mybatis-35x">1.1 SqlSession概述(基于MyBatis 3.5.x)</h3>
<p>SqlSession是MyBatis的核心接口,代表与数据库的一次会话。它是MyBatis架构中接口层的重要组成部分,为用户提供了简洁的API来执行数据库操作。</p>
<p><strong>SqlSession的核心职责</strong>:</p>
<ol>
<li><strong>数据库操作</strong>:提供CRUD操作的统一接口</li>
<li><strong>事务管理</strong>:管理数据库事务的提交和回滚</li>
<li><strong>Mapper管理</strong>:获取Mapper接口的动态代理对象</li>
<li><strong>会话管理</strong>:管理会话的生命周期和资源释放</li>
</ol>
<p><strong>重要提示</strong>:理解SqlSession的设计和实现是深入MyBatis源码的关键,后续的Executor、StatementHandler等组件都围绕SqlSession展开。</p>
<h2 id="2-sqlsession接口设计分析">2. SqlSession接口设计分析</h2>
<h3 id="21-sqlsession接口结构">2.1 SqlSession接口结构</h3>
<p>让我们深入分析SqlSession接口的设计:</p>
<pre><code class="language-java">package org.apache.ibatis.session;

import java.io.Closeable;
import java.sql.Connection;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.executor.BatchResult;
import org.apache.ibatis.executor.result.ResultHandler;

public interface SqlSession extends Closeable {
    // 查询操作
    &lt;T&gt; T selectOne(String statement);
    &lt;T&gt; T selectOne(String statement, Object parameter);
    &lt;E&gt; List&lt;E&gt; selectList(String statement);
    &lt;E&gt; List&lt;E&gt; selectList(String statement, Object parameter);
    &lt;E&gt; List&lt;E&gt; selectList(String statement, Object parameter, RowBounds rowBounds);

    // Map查询操作
    &lt;K, V&gt; Map&lt;K, V&gt; selectMap(String statement, String mapKey);
    &lt;K, V&gt; Map&lt;K, V&gt; selectMap(String statement, Object parameter, String mapKey);
    &lt;K, V&gt; Map&lt;K, V&gt; selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);

    // 游标查询
    &lt;T&gt; Cursor&lt;T&gt; selectCursor(String statement);
    &lt;T&gt; Cursor&lt;T&gt; selectCursor(String statement, Object parameter);
    &lt;T&gt; Cursor&lt;T&gt; selectCursor(String statement, Object parameter, RowBounds rowBounds);

    // 自定义结果处理(流式结果)
    void select(String statement, Object parameter, ResultHandler handler);
    void select(String statement, ResultHandler handler);
    void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);

    // 更新操作
    int insert(String statement);
    int insert(String statement, Object parameter);
    int update(String statement);
    int update(String statement, Object parameter);
    int delete(String statement);
    int delete(String statement, Object parameter);

    // 事务管理
    void commit();
    void commit(boolean force);
    void rollback();
    void rollback(boolean force);

    // 批量操作
    List&lt;BatchResult&gt; flushStatements();

    // Mapper获取
    &lt;T&gt; T getMapper(Class&lt;T&gt; type);

    // 连接管理
    Connection getConnection();

    // 配置获取
    Configuration getConfiguration();

    // 缓存管理
    void clearCache();
}
</code></pre>
<h3 id="22-接口设计特点分析">2.2 接口设计特点分析</h3>
<h4 id="221-泛型设计">2.2.1 泛型设计</h4>
<pre><code class="language-java">// 泛型设计提供了类型安全
&lt;T&gt; T selectOne(String statement, Object parameter);
&lt;E&gt; List&lt;E&gt; selectList(String statement, Object parameter);
</code></pre>
<p><strong>优势</strong>:</p>
<ul>
<li><strong>类型安全</strong>:编译时类型检查,避免运行时类型转换错误</li>
<li><strong>代码简洁</strong>:无需手动类型转换</li>
<li><strong>IDE支持</strong>:更好的代码提示和重构支持</li>
</ul>
<h4 id="222-resulthandler自定义结果处理">2.2.2 ResultHandler自定义结果处理</h4>
<pre><code class="language-java">// 支持自定义结果处理,适用于流式结果处理
void select(String statement, Object parameter, ResultHandler handler);
void select(String statement, ResultHandler handler);
void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);
</code></pre>
<p><strong>使用场景</strong>:</p>
<ul>
<li><strong>流式处理</strong>:处理大量数据时避免内存溢出</li>
<li><strong>自定义转换</strong>:对结果进行自定义处理</li>
<li><strong>实时处理</strong>:边查询边处理结果</li>
</ul>
<p><strong>示例用法</strong>:</p>
<pre><code class="language-java">// 流式处理大量数据
session.select("selectAllUsers", null, new ResultHandler&lt;User&gt;() {
    @Override
    public void handleResult(ResultContext&lt;? extends User&gt; resultContext) {
      User user = resultContext.getResultObject();
      // 实时处理每个用户数据
      processUser(user);
    }
});
</code></pre>
<h4 id="223-方法重载设计">2.2.3 方法重载设计</h4>
<pre><code class="language-java">// 支持不同参数组合
&lt;T&gt; T selectOne(String statement);
&lt;T&gt; T selectOne(String statement, Object parameter);
&lt;E&gt; List&lt;E&gt; selectList(String statement, Object parameter);
&lt;E&gt; List&lt;E&gt; selectList(String statement, Object parameter, RowBounds rowBounds);
</code></pre>
<p><strong>优势</strong>:</p>
<ul>
<li><strong>使用灵活</strong>:支持不同使用场景</li>
<li><strong>向后兼容</strong>:保持API的向后兼容性</li>
<li><strong>渐进式学习</strong>:从简单到复杂的使用方式</li>
</ul>
<h4 id="224-资源管理设计">2.2.4 资源管理设计</h4>
<pre><code class="language-java">public interface SqlSession extends Closeable {
    // 继承Closeable接口,支持try-with-resources语法
}
</code></pre>
<p><strong>优势</strong>:</p>
<ul>
<li><strong>自动资源管理</strong>:支持try-with-resources语法</li>
<li><strong>防止资源泄漏</strong>:确保资源正确释放</li>
<li><strong>代码简洁</strong>:减少样板代码</li>
</ul>
<h2 id="3-sqlsessionfactory工厂模式分析">3. SqlSessionFactory工厂模式分析</h2>
<h3 id="31-sqlsessionfactory接口设计">3.1 SqlSessionFactory接口设计</h3>
<p>SqlSessionFactory是创建SqlSession的工厂接口,采用工厂模式设计:</p>
<pre><code class="language-java">package org.apache.ibatis.session;

import java.sql.Connection;

public interface SqlSessionFactory {
    // 基本创建方法
    SqlSession openSession();
    SqlSession openSession(boolean autoCommit);
    SqlSession openSession(Connection connection);

    // 执行器类型指定
    SqlSession openSession(ExecutorType execType);
    SqlSession openSession(ExecutorType execType, boolean autoCommit);
    SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
    SqlSession openSession(ExecutorType execType, Connection connection);

    // 事务隔离级别指定
    SqlSession openSession(TransactionIsolationLevel level);

    // 配置获取
    Configuration getConfiguration();
}
</code></pre>
<h3 id="32-defaultsqlsessionfactory实现分析">3.2 DefaultSqlSessionFactory实现分析</h3>
<p>DefaultSqlSessionFactory是SqlSessionFactory的默认实现,让我们深入分析其源码:</p>
<pre><code class="language-java">package org.apache.ibatis.session.defaults;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.managed.ManagedTransactionFactory;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.executor.ErrorContext;

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);
    }

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

    @Override
    public SqlSession openSession(ExecutorType execType) {
      return openSessionFromDataSource(execType, null, false);
    }

    // 核心创建方法
    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
      Transaction tx = null;
      try {
            // 1. 获取环境配置
            final Environment environment = configuration.getEnvironment();
      
            // 2. 获取事务工厂
            final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      
            // 3. 创建事务
            tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      
            // 4. 创建执行器
            final Executor executor = configuration.newExecutor(tx, execType);
      
            // 5. 创建SqlSession
            return createSqlSession(configuration, executor, autoCommit);
      } catch (Exception e) {
            closeTransaction(tx);
            throw ExceptionFactory.wrapException("Error opening session.Cause: " + e, e);
      } finally {
            ErrorContext.instance().reset();
      }
    }

    protected SqlSession createSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
      return new DefaultSqlSession(configuration, executor, autoCommit);
    }
}
</code></pre>
<h3 id="33-工厂模式的优势">3.3 工厂模式的优势</h3>
<h4 id="331-封装复杂性">3.3.1 封装复杂性</h4>
<pre><code class="language-java">// 用户只需要调用简单的方法
SqlSession session = sqlSessionFactory.openSession();

// 内部复杂的创建过程被封装
// 1. 环境配置获取
// 2. 事务工厂创建
// 3. 事务对象创建
// 4. 执行器创建
// 5. SqlSession创建
</code></pre>
<h4 id="332-参数灵活性">3.3.2 参数灵活性</h4>
<pre><code class="language-java">// 支持多种参数组合
SqlSession session1 = sqlSessionFactory.openSession(); // 默认配置
SqlSession session2 = sqlSessionFactory.openSession(true); // 自动提交
SqlSession session3 = sqlSessionFactory.openSession(ExecutorType.BATCH); // 批处理执行器
</code></pre>
<h4 id="333-配置驱动">3.3.3 配置驱动</h4>
<pre><code class="language-java">// 基于Configuration配置创建SqlSession
final Executor executor = configuration.newExecutor(tx, execType);
</code></pre>
<h2 id="4-sqlsession生命周期管理">4. SqlSession生命周期管理</h2>
<h3 id="41-生命周期阶段">4.1 生命周期阶段</h3>
<p>SqlSession的生命周期可以分为以下几个阶段:</p>
<div class="mermaid">graph TD
    A["🔄 创建阶段"] --&gt;|openSession| B["⚡ 使用阶段"]
    B --&gt;|commit/rollback| C["🔒 事务管理阶段"]
    C --&gt;|close| D["🧹 资源释放阶段"]

    A1["📋 获取配置"] --&gt;|Environment| A2["🏗️ 创建事务"]
    A2 --&gt;|Transaction| A3["⚙️ 创建执行器"]
    A3 --&gt;|Executor| A4["🎯 创建SqlSession"]

    B1["💾 执行SQL"] --&gt;|select/update| B2["📊 结果处理"]
    B2 --&gt;|getMapper| B3["🔗 Mapper调用"]

    C1["🚀 事务开始"] --&gt;|操作完成| C2["✅ 提交/回滚"]
    C2 --&gt;|结束事务| C3["🏁 事务结束"]

    D1["🔧 关闭执行器"] --&gt;|executor.close| D2["🔐 关闭事务"]
    D2 --&gt;|tx.close| D3["🔌 关闭连接"]
    D3 --&gt;|clearCache| D4["🗑️ 清理缓存"]

    classDef createPhase fill:#e1f5fe,stroke:#01579b,stroke-width:2px
    classDef usePhase fill:#f3e5f5,stroke:#4a148c,stroke-width:2px
    classDef transactionPhase fill:#fff3e0,stroke:#e65100,stroke-width:2px
    classDef releasePhase fill:#e8f5e8,stroke:#1b5e20,stroke-width:2px

    class A,A1,A2,A3,A4 createPhase
    class B,B1,B2,B3 usePhase
    class C,C1,C2,C3 transactionPhase
    class D,D1,D2,D3,D4 releasePhase
</div><h3 id="42-创建阶段详细分析">4.2 创建阶段详细分析</h3>
<h4 id="421-配置获取">4.2.1 配置获取</h4>
<pre><code class="language-java">// 从Configuration获取环境配置
final Environment environment = configuration.getEnvironment();
</code></pre>
<p><strong>Environment包含</strong>:</p>
<ul>
<li><strong>DataSource</strong>:数据源配置</li>
<li><strong>TransactionFactory</strong>:事务工厂配置</li>
<li><strong>Id</strong>:环境标识</li>
</ul>
<h4 id="422-事务创建">4.2.2 事务创建</h4>
<pre><code class="language-java">// 创建事务对象
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
</code></pre>
<p><strong>事务创建过程</strong>:</p>
<ol>
<li><strong>获取事务工厂</strong>:从环境配置获取TransactionFactory</li>
<li><strong>创建事务对象</strong>:使用DataSource和参数创建Transaction</li>
<li><strong>设置事务属性</strong>:隔离级别、自动提交等</li>
</ol>
<h4 id="423-执行器创建">4.2.3 执行器创建</h4>
<pre><code class="language-java">// 创建执行器
final Executor executor = configuration.newExecutor(tx, execType);
</code></pre>
<p><strong>执行器创建过程</strong>:</p>
<ol>
<li><strong>执行器类型选择</strong>:根据ExecutorType选择具体实现</li>
<li><strong>缓存包装</strong>:如果启用缓存,用CachingExecutor包装</li>
<li><strong>插件应用</strong>:应用所有配置的插件</li>
</ol>
<h4 id="424-sqlsession创建">4.2.4 SqlSession创建</h4>
<pre><code class="language-java">// 创建SqlSession对象
return new DefaultSqlSession(configuration, executor, autoCommit);
</code></pre>
<h3 id="43-使用阶段分析">4.3 使用阶段分析</h3>
<h4 id="431-sql执行流程">4.3.1 SQL执行流程</h4>
<pre><code class="language-java">// 用户调用
User user = session.selectOne("selectUser", 1);

// 内部执行流程
public &lt;T&gt; T selectOne(String statement, Object parameter) {
    List&lt;T&gt; list = this.selectList(statement, parameter);
    if (list.size() == 1) {
      return list.get(0);
    }
    if (list.size() &gt; 1) {
      throw new TooManyResultsException("Expected one result...");
    } else {
      return null;
    }
}
</code></pre>
<h4 id="432-mapper获取流程">4.3.2 Mapper获取流程</h4>
<pre><code class="language-java">// 用户调用
UserMapper mapper = session.getMapper(UserMapper.class);

// 内部实现
@Override
public &lt;T&gt; T getMapper(Class&lt;T&gt; type) {
    return configuration.getMapper(type, this);
}
</code></pre>
<h3 id="44-资源释放阶段">4.4 资源释放阶段</h3>
<h4 id="441-手动关闭">4.4.1 手动关闭</h4>
<pre><code class="language-java">// 手动关闭SqlSession
session.close();

// 内部关闭流程
@Override
public void close() {
    try {
      executor.close(isCommitOrRollbackRequired(false));
    } catch (SQLException e) {
      throw ExceptionFactory.wrapException("Error closing SqlSession.Cause: " + e, e);
    } finally {
      // 清理资源
      dirty = false;
      executor = null;
      configuration = null;
    }
}
</code></pre>
<h4 id="442-自动关闭">4.4.2 自动关闭</h4>
<pre><code class="language-java">// 使用try-with-resources语法
try (SqlSession session = sqlSessionFactory.openSession()) {
    User user = session.selectOne("selectUser", 1);
    // 自动关闭
}
</code></pre>
<h2 id="5-defaultsqlsession实现分析">5. DefaultSqlSession实现分析</h2>
<h3 id="51-defaultsqlsession类结构">5.1 DefaultSqlSession类结构</h3>
<pre><code class="language-java">public class DefaultSqlSession implements SqlSession {
    private final Configuration configuration;
    private final Executor executor;
    private final boolean autoCommit;
    private boolean dirty;
    private List&lt;Cursor&lt;?&gt;&gt; cursorList;

    public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
      this.configuration = configuration;
      this.executor = executor;
      this.dirty = false;
      this.autoCommit = autoCommit;
    }
}
</code></pre>
<h3 id="52-核心方法实现分析">5.2 核心方法实现分析</h3>
<h4 id="521-selectone方法实现">5.2.1 selectOne方法实现</h4>
<pre><code class="language-java">@Override
public &lt;T&gt; T selectOne(String statement, Object parameter) {
    // 调用selectList获取结果
    List&lt;T&gt; list = this.selectList(statement, parameter);

    // 结果数量验证
    if (list.size() == 1) {
      return list.get(0);
    }
    if (list.size() &gt; 1) {
      throw new TooManyResultsException(
            "Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
    } else {
      return null;
    }
}
</code></pre>
<p><strong>设计亮点</strong>:</p>
<ul>
<li><strong>复用selectList</strong>:避免代码重复</li>
<li><strong>结果验证</strong>:确保返回单个结果</li>
<li><strong>异常处理</strong>:结果过多时抛出异常</li>
</ul>
<h4 id="522-selectlist方法实现">5.2.2 selectList方法实现</h4>
<pre><code class="language-java">@Override
public &lt;E&gt; List&lt;E&gt; selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      // 1. 获取MappedStatement
      MappedStatement ms = configuration.getMappedStatement(statement);
   
      // 2. 委托给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();
    }
}
</code></pre>
<p><strong>执行流程</strong>:</p>
<ol>
<li><strong>获取映射语句</strong>:从Configuration获取MappedStatement</li>
<li><strong>参数包装</strong>:处理集合参数</li>
<li><strong>委托执行</strong>:委托给Executor执行查询</li>
<li><strong>异常处理</strong>:统一异常处理</li>
<li><strong>资源清理</strong>:重置错误上下文</li>
</ol>
<h4 id="523-update方法实现">5.2.3 update方法实现</h4>
<pre><code class="language-java">@Override
public int update(String statement, Object parameter) {
    try {
      // 1. 标记为脏数据
      dirty = true;
   
      // 2. 获取MappedStatement
      MappedStatement ms = configuration.getMappedStatement(statement);
   
      // 3. 委托给Executor执行
      return executor.update(ms, wrapCollection(parameter));
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error updating database.Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
}
</code></pre>
<p><strong>设计特点</strong>:</p>
<ul>
<li><strong>脏数据标记</strong>:标记SqlSession为脏状态</li>
<li><strong>统一处理</strong>:insert、update、delete都使用相同逻辑</li>
</ul>
<h4 id="524-事务管理方法">5.2.4 事务管理方法</h4>
<pre><code class="language-java">@Override
public void commit() {
    commit(false);
}

@Override
public void commit(boolean force) {
    try {
      executor.commit(isCommitOrRollbackRequired(force));
      dirty = false;
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error committing transaction.Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
}

@Override
public void rollback() {
    rollback(false);
}

@Override
public void rollback(boolean force) {
    try {
      executor.rollback(isCommitOrRollbackRequired(force));
      dirty = false;
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error rolling back transaction.Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
}
</code></pre>
<p><strong>事务管理特点</strong>:</p>
<ul>
<li><strong>条件提交</strong>:根据dirty状态决定是否需要提交</li>
<li><strong>强制选项</strong>:支持强制提交/回滚</li>
<li><strong>状态重置</strong>:提交/回滚后重置dirty状态</li>
</ul>
<h2 id="6-executor执行器体系分析">6. Executor执行器体系分析</h2>
<h3 id="61-executor接口设计">6.1 Executor接口设计</h3>
<p>Executor是MyBatis执行器的核心接口,其继承关系如下:</p>
<div class="mermaid">classDiagram
    class Executor {
      &lt;&lt;interface&gt;&gt;
      +update()
      +query()
      +queryCursor()
      +flushStatements()
      +commit()
      +rollback()
      +createCacheKey()
      +clearLocalCache()
    }
    class BaseExecutor {
      &lt;&lt;abstract&gt;&gt;
      #doQuery()
      #doUpdate()
      #doFlushStatements()
    }
    class SimpleExecutor {
      +doQuery()
      +doUpdate()
    }
    class ReuseExecutor {
      +doQuery()
      +doUpdate()
      -Map~String,Statement~ statementMap
    }
    class BatchExecutor {
      +doQuery()
      +doUpdate()
      -List~Statement~ statementList
      -List~BatchResult~ batchResultList
    }
    class CachingExecutor {
      +query()
      +update()
      -Executor delegate
      -TransactionalCacheManager tcm
    }
    Executor &lt;|.. BaseExecutor
    BaseExecutor &lt;|-- SimpleExecutor
    BaseExecutor &lt;|-- ReuseExecutor
    BaseExecutor &lt;|-- BatchExecutor
    Executor &lt;|.. CachingExecutor
</div><p>Executor是MyBatis执行器的核心接口:</p>
<pre><code class="language-java">public interface Executor {
    // 查询操作
    &lt;E&gt; List&lt;E&gt; query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
    &lt;E&gt; List&lt;E&gt; query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
    &lt;E&gt; Cursor&lt;E&gt; queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;

    // 更新操作
    int update(MappedStatement ms, Object parameter) throws SQLException;

    // 事务管理
    void commit(boolean required) throws SQLException;
    void rollback(boolean required) throws SQLException;

    // 缓存管理
    CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
    boolean isCached(MappedStatement ms, CacheKey key);
    void clearLocalCache();

    // 延迟加载
    void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class&lt;?&gt; targetType);

    // 批量操作
    List&lt;BatchResult&gt; flushStatements() throws SQLException;

    // 资源管理
    Transaction getTransaction();
    void close(boolean forceRollback);
    boolean isClosed();
}
</code></pre>
<h3 id="62-baseexecutor抽象基类">6.2 BaseExecutor抽象基类</h3>
<p>BaseExecutor是Executor的抽象基类,实现了模板方法模式:</p>
<pre><code class="language-java">public abstract class BaseExecutor implements Executor {
    protected Transaction transaction;
    protected Executor wrapper;
    protected PerpetualCache localCache;
    protected PerpetualCache localOutputParameterCache;
    protected Configuration configuration;
    protected int queryStack;
    private boolean closed;

    // 模板方法:查询操作
    @Override
    public &lt;E&gt; List&lt;E&gt; 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 &lt;E&gt; List&lt;E&gt; query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException {
      ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
      if (closed) {
            throw new ExecutorException("Executor was closed.");
      }
      if (queryStack == 0 &amp;&amp; ms.isFlushCacheRequired()) {
            clearLocalCache();
      }
      List&lt;E&gt; list;
      try {
            queryStack++;
            list = resultHandler == null ? (List&lt;E&gt;) localCache.getObject(cacheKey) : null;
            if (list != null) {
                handleLocallyCachedOutputParameters(ms, cacheKey, parameter, boundSql);
            } else {
                list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, cacheKey, boundSql);
            }
      } finally {
            queryStack--;
      }
      if (queryStack == 0) {
            for (DeferredLoad deferredLoad : deferredLoads) {
                deferredLoad.load();
            }
            deferredLoads.clear();
            if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
                clearLocalCache();
            }
      }
      return list;
    }

    // 抽象方法:子类实现具体的数据库查询
    protected abstract &lt;E&gt; List&lt;E&gt; doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException;

    // 模板方法:更新操作
    @Override
    public int update(MappedStatement ms, Object parameter) throws SQLException {
      ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
      if (closed) {
            throw new ExecutorException("Executor was closed.");
      }
      clearLocalCache();
      return doUpdate(ms, parameter);
    }

    // 抽象方法:子类实现具体的数据库更新
    protected abstract int doUpdate(MappedStatement ms, Object parameter) throws SQLException;
}
</code></pre>
<h3 id="63-具体执行器实现">6.3 具体执行器实现</h3>
<h4 id="631-simpleexecutor">6.3.1 SimpleExecutor</h4>
<pre><code class="language-java">public class SimpleExecutor extends BaseExecutor {

    public SimpleExecutor(Configuration configuration, Transaction transaction) {
      super(configuration, transaction);
    }

    @Override
    public &lt;E&gt; List&lt;E&gt; 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());
            return handler.query(stmt, resultHandler);
      } finally {
            closeStatement(stmt);
      }
    }

    @Override
    public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
      Statement stmt = null;
      try {
            Configuration configuration = ms.getConfiguration();
            StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
            stmt = prepareStatement(handler, ms.getStatementLog());
            return handler.update(stmt);
      } finally {
            closeStatement(stmt);
      }
    }

    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
      Statement stmt;
      Connection connection = getConnection(statementLog);
      stmt = handler.prepare(connection, transaction.getTimeout());
      handler.parameterize(stmt);
      return stmt;
    }
}
</code></pre>
<p><strong>特点</strong>:</p>
<ul>
<li><strong>简单实现</strong>:每次执行都创建新的Statement</li>
<li><strong>资源管理</strong>:及时关闭Statement和Connection</li>
<li><strong>性能考虑</strong>:适合单次执行场景</li>
</ul>
<h4 id="632-reuseexecutor">6.3.2 ReuseExecutor</h4>
<pre><code class="language-java">public class ReuseExecutor extends BaseExecutor {
    private final Map&lt;String, Statement&gt; statementMap = new HashMap&lt;&gt;();

    @Override
    public &lt;E&gt; List&lt;E&gt; doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      Statement stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.query(stmt, resultHandler);
    }

    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
      Statement stmt;
      BoundSql boundSql = handler.getBoundSql();
      String sql = boundSql.getSql();
      if (hasStatementFor(sql)) {
            stmt = getStatement(sql);
            applyTransactionTimeout(stmt);
      } else {
            Connection connection = getConnection(statementLog);
            stmt = handler.prepare(connection, transaction.getTimeout());
            putStatement(sql, stmt);
      }
      handler.parameterize(stmt);
      return stmt;
    }

    private boolean hasStatementFor(String sql) {
      return statementMap.containsKey(sql);
    }

    private Statement getStatement(String sql) {
      return statementMap.get(sql);
    }

    private void putStatement(String sql, Statement stmt) {
      statementMap.put(sql, stmt);
    }
}
</code></pre>
<p><strong>特点</strong>:</p>
<ul>
<li><strong>Statement重用</strong>:相同SQL重用Statement对象</li>
<li><strong>性能优化</strong>:减少Statement创建开销</li>
<li><strong>内存管理</strong>:需要管理Statement缓存</li>
</ul>
<h4 id="633-batchexecutor">6.3.3 BatchExecutor</h4>
<pre><code class="language-java">public class BatchExecutor extends BaseExecutor {
    private final List&lt;Statement&gt; statementList = new ArrayList&lt;&gt;();
    private final List&lt;BatchResult&gt; batchResultList = new ArrayList&lt;&gt;();
    private String currentSql;
    private MappedStatement currentStatement;

    @Override
    public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
      final Configuration configuration = ms.getConfiguration();
      final StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
      final BoundSql boundSql = handler.getBoundSql();
      final String sql = boundSql.getSql();
      final StatementType statementType = ms.getStatementType();
   
      if (sql.equals(currentSql) &amp;&amp; statementType == currentStatement.getStatementType()) {
            // 相同SQL,重用Statement
            final Statement stmt = statementList.get(statementList.size() - 1);
            applyTransactionTimeout(stmt);
            handler.parameterize(stmt);
            BatchResult batchResult = batchResultList.get(batchResultList.size() - 1);
            batchResult.addParameterObject(parameter);
            return BATCH_UPDATE_RETURN_VALUE;
      } else {
            // 不同SQL,创建新Statement
            final Statement stmt;
            if (sql.equals(currentSql) &amp;&amp; ms.getStatementType() == currentStatement.getStatementType()) {
                int last = statementList.size() - 1;
                stmt = statementList.get(last);
                applyTransactionTimeout(stmt);
                handler.parameterize(stmt);
                BatchResult batchResult = batchResultList.get(last);
                batchResult.addParameterObject(parameter);
            } else {
                Connection connection = getConnection(ms.getStatementLog());
                stmt = handler.prepare(connection, transaction.getTimeout());
                handler.parameterize(stmt);
                currentSql = sql;
                currentStatement = ms;
                statementList.add(stmt);
                batchResultList.add(new BatchResult(ms, sql, parameter));
            }
            handler.batch(stmt);
            return BATCH_UPDATE_RETURN_VALUE;
      }
    }
}
</code></pre>
<p><strong>特点</strong>:</p>
<ul>
<li><strong>批量执行</strong>:收集多个SQL语句批量执行</li>
<li><strong>性能优化</strong>:减少数据库交互次数</li>
<li><strong>结果管理</strong>:管理批量执行的结果</li>
</ul>
<h3 id="64-cachingexecutor缓存装饰器">6.4 CachingExecutor缓存装饰器</h3>
<pre><code class="language-java">public class CachingExecutor implements Executor {
    private final Executor delegate;
    private final TransactionalCacheManager tcm = new TransactionalCacheManager();

    public CachingExecutor(Executor delegate) {
      this.delegate = delegate;
      delegate.setExecutorWrapper(this);
    }

    @Override
    public &lt;E&gt; List&lt;E&gt; query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
      Cache cache = ms.getCache();
      if (cache != null) {
            flushCacheIfRequired(ms);
            if (ms.isUseCache() &amp;&amp; resultHandler == null) {
                ensureNoOutParams(ms, boundSql);
                @SuppressWarnings("unchecked")
                List&lt;E&gt; list = (List&lt;E&gt;) tcm.getObject(cache, key);
                if (list == null) {
                  list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
                  tcm.putObject(cache, key, list);
                }
                return list;
            }
      }
      return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    }

    @Override
    public int update(MappedStatement ms, Object parameterObject) throws SQLException {
      flushCacheIfRequired(ms);
      return delegate.update(ms, parameterObject);
    }

    private void flushCacheIfRequired(MappedStatement ms) {
      Cache cache = ms.getCache();
      if (cache != null &amp;&amp; ms.isFlushCacheRequired()) {
            tcm.clear(cache);
      }
    }
}
</code></pre>
<p><strong>特点</strong>:</p>
<ul>
<li><strong>装饰器模式</strong>:包装其他执行器,添加缓存功能</li>
<li><strong>二级缓存</strong>:支持跨SqlSession的缓存</li>
<li><strong>缓存管理</strong>:自动管理缓存的刷新和清理</li>
</ul>
<h3 id="64-executor类型总结">6.4 Executor类型总结</h3>
<table>
<thead>
<tr>
<th>执行器类型</th>
<th>特点</th>
<th>适用场景</th>
<th>性能特点</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>SimpleExecutor</strong></td>
<td>每次执行创建新Statement</td>
<td>单次执行、简单查询</td>
<td>简单直接,适合轻量级操作</td>
</tr>
<tr>
<td><strong>ReuseExecutor</strong></td>
<td>重用相同SQL的Statement</td>
<td>重复执行相同SQL</td>
<td>减少Statement创建开销</td>
</tr>
<tr>
<td><strong>BatchExecutor</strong></td>
<td>批量执行多个SQL</td>
<td>批量插入、更新、删除</td>
<td>大幅减少数据库交互次数</td>
</tr>
<tr>
<td><strong>CachingExecutor</strong></td>
<td>装饰器模式,添加缓存</td>
<td>需要缓存的查询场景</td>
<td>避免重复查询,提升性能</td>
</tr>
</tbody>
</table>
<p><strong>选择建议</strong>:</p>
<ul>
<li><strong>默认场景</strong>:使用SimpleExecutor,简单可靠</li>
<li><strong>重复SQL</strong>:使用ReuseExecutor,提升性能</li>
<li><strong>批量操作</strong>:使用BatchExecutor,大幅提升批量操作性能</li>
<li><strong>缓存需求</strong>:配合CachingExecutor,提升查询性能</li>
</ul>
<h2 id="7-实践案例">7. 实践案例</h2>
<h3 id="71-跟踪sqlsession创建流程">7.1 跟踪SqlSession创建流程</h3>
<p>让我们通过一个完整的例子来跟踪SqlSession的创建流程:</p>
<h4 id="711-mybatis-configxml配置文件">7.1.1 mybatis-config.xml配置文件</h4>
<pre><code class="language-xml">&lt;?xml version="1.0" encoding="UTF-8" ?&gt;
&lt;!DOCTYPE configuration
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-config.dtd"&gt;
&lt;configuration&gt;
    &lt;environments default="development"&gt;
      &lt;environment id="development"&gt;
            &lt;transactionManager type="JDBC"/&gt;
            &lt;dataSource type="POOLED"&gt;
                &lt;property name="driver" value="com.mysql.cj.jdbc.Driver"/&gt;
                &lt;property name="url" value="jdbc:mysql://localhost:3306/mybatis_test"/&gt;
                &lt;property name="username" value="root"/&gt;
                &lt;property name="password" value="password"/&gt;
            &lt;/dataSource&gt;
      &lt;/environment&gt;
    &lt;/environments&gt;

    &lt;mappers&gt;
      &lt;mapper resource="UserMapper.xml"/&gt;
    &lt;/mappers&gt;
&lt;/configuration&gt;
</code></pre>
<h4 id="712-usermapperjava接口">7.1.2 UserMapper.java接口</h4>
<pre><code class="language-java">package com.example.mapper;

import com.example.model.User;
import java.util.List;

public interface UserMapper {
    User selectUser(int id);
    List&lt;User&gt; selectAllUsers();
    int insertUser(User user);
    int updateUser(User user);
    int deleteUser(int id);
}
</code></pre>
<h4 id="713-sqlsession创建示例">7.1.3 SqlSession创建示例</h4>
<pre><code class="language-java">package com.example;

import com.example.mapper.UserMapper;
import com.example.model.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class SqlSessionCreationExample {
    public static void main(String[] args) throws IOException {
      // 1. 创建SqlSessionFactoryBuilder
      SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
   
      // 2. 解析配置文件,创建SqlSessionFactory
      String resource = "mybatis-config.xml";
      InputStream inputStream = Resources.getResourceAsStream(resource);
      SqlSessionFactory sqlSessionFactory = builder.build(inputStream);
   
      // 3. 创建SqlSession
      SqlSession session = sqlSessionFactory.openSession();
   
      // 4. 使用SqlSession
      User user = session.selectOne("selectUser", 1);
      System.out.println("查询结果: " + user);
      
      // 5. 使用Mapper接口
      UserMapper userMapper = session.getMapper(UserMapper.class);
      User user2 = userMapper.selectUser(1);
      System.out.println("Mapper查询结果: " + user2);
   
      // 6. 关闭SqlSession
      session.close();
    }
}
</code></pre>
<p><strong>执行流程分析</strong>:</p>
<ol>
<li>
<p><strong>SqlSessionFactoryBuilder.build()</strong>:</p>
<ul>
<li>创建XMLConfigBuilder</li>
<li>解析配置文件</li>
<li>创建Configuration对象</li>
<li>创建DefaultSqlSessionFactory</li>
</ul>
</li>
<li>
<p><strong>DefaultSqlSessionFactory.openSession()</strong>:</p>
<ul>
<li>调用openSessionFromDataSource()</li>
<li>获取Environment配置</li>
<li>创建TransactionFactory</li>
<li>创建Transaction对象</li>
<li>创建Executor</li>
<li>创建DefaultSqlSession</li>
</ul>
</li>
<li>
<p><strong>DefaultSqlSession使用</strong>:</p>
<ul>
<li>调用selectOne()方法</li>
<li>内部调用selectList()</li>
<li>委托给Executor执行</li>
<li>返回查询结果</li>
</ul>
</li>
<li>
<p><strong>资源释放</strong>:</p>
<ul>
<li>调用session.close()</li>
<li>关闭Executor</li>
<li>关闭Transaction</li>
<li>关闭Connection</li>
</ul>
</li>
</ol>
<h3 id="72-分析不同executor类型的使用场景">7.2 分析不同Executor类型的使用场景</h3>
<pre><code class="language-java">public class ExecutorTypeExample {
    public static void main(String[] args) {
      SqlSessionFactory sqlSessionFactory = createSqlSessionFactory();
   
      // 1. 使用SimpleExecutor(默认)
      try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.SIMPLE)) {
            System.out.println("使用SimpleExecutor执行查询");
            User user = session.selectOne("selectUser", 1);
            System.out.println("查询结果: " + user);
      }
   
      // 2. 使用ReuseExecutor
      try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.REUSE)) {
            System.out.println("使用ReuseExecutor执行查询");
            User user = session.selectOne("selectUser", 1);
            System.out.println("查询结果: " + user);
      }
   
      // 3. 使用BatchExecutor
      try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
            System.out.println("使用BatchExecutor执行批量更新");
      
            // 批量插入
            for (int i = 1; i &lt;= 10; i++) {
                User user = new User(i, "User" + i, "user" + i + "@example.com");
                session.insert("insertUser", user);
            }
      
            // 执行批量操作
            List&lt;BatchResult&gt; results = session.flushStatements();
            System.out.println("批量执行结果数量: " + results.size());
      
            // 提交事务
            session.commit();
      }
    }
}
</code></pre>
<h3 id="73-分析sqlsession的生命周期管理">7.3 分析SqlSession的生命周期管理</h3>
<pre><code class="language-java">public class SqlSessionLifecycleExample {
    public static void main(String[] args) {
      SqlSessionFactory sqlSessionFactory = createSqlSessionFactory();
   
      // 1. 手动管理生命周期
      SqlSession session = sqlSessionFactory.openSession();
      try {
            // 执行业务操作
            User user = session.selectOne("selectUser", 1);
            System.out.println("查询结果: " + user);
      
            // 提交事务
            session.commit();
      } catch (Exception e) {
            // 回滚事务
            session.rollback();
            e.printStackTrace();
      } finally {
            // 关闭会话
            session.close();
      }
   
      // 2. 自动管理生命周期(推荐方式)
      try (SqlSession session2 = sqlSessionFactory.openSession()) {
            User user = session2.selectOne("selectUser", 1);
            System.out.println("查询结果: " + user);
            session2.commit();
      } catch (Exception e) {
            e.printStackTrace();
      }
    }
}
</code></pre>
<h2 id="8--后续文章规划">8.后续文章规划</h2>
<p>基于SqlSession的理解,后续我们将深入分析:</p>
<ol>
<li>
<p><strong>第4篇</strong>:Mapper接口的动态代理机制</p>
<ul>
<li>MapperProxy源码分析</li>
<li>接口方法解析</li>
<li>参数绑定和结果映射</li>
</ul>
</li>
<li>
<p><strong>第5篇</strong>:Executor执行器体系详解</p>
<ul>
<li>BaseExecutor模板方法模式</li>
<li>StatementHandler语句处理器</li>
<li>ParameterHandler参数处理器</li>
<li>ResultSetHandler结果集处理器</li>
</ul>
</li>
<li>
<p><strong>第6篇</strong>:StatementHandler语句处理器</p>
<ul>
<li>RoutingStatementHandler路由机制</li>
<li>PreparedStatementHandler实现</li>
<li>SQL预处理和参数绑定</li>
</ul>
</li>
</ol>
<h2 id="总结">总结</h2>
<p>通过本文的学习,我们深入了解了MyBatis SqlSession的核心机制:</p>
<ol>
<li><strong>SqlSession接口</strong>:提供了完整的数据库操作API,支持查询、更新、事务管理等功能</li>
<li><strong>SqlSessionFactory</strong>:采用工厂模式,封装了SqlSession的创建复杂性</li>
<li><strong>DefaultSqlSession</strong>:SqlSession的默认实现,是用户操作数据库的主要入口</li>
<li><strong>Executor执行器</strong>:SqlSession的核心组件,负责具体的SQL执行</li>
<li><strong>生命周期管理</strong>:从创建到销毁的完整生命周期管理</li>
</ol>
<p><strong>重要提示</strong>:SqlSession是MyBatis架构的核心,理解SqlSession对于后续的源码学习至关重要。通过源码分析,我们能够更深入地理解MyBatis的设计思想和实现细节。</p>
<p>在下一篇文章中,我们将基于SqlSession的理解,深入分析Mapper接口的动态代理机制,了解MyBatis是如何实现接口代理的。</p>
<hr>
<p><strong>思考题</strong>:</p>
<ol>
<li><strong>为什么MyBatis要设计SqlSession接口?这种设计有什么优势?</strong></li>
<li><strong>SqlSessionFactory的工厂模式设计有什么好处?</strong></li>
<li><strong>不同Executor类型的适用场景是什么?如何选择?</strong></li>
<li><strong>SqlSession的生命周期管理需要注意哪些问题?</strong></li>
</ol>
<p><strong>下篇预告</strong>:在下一篇文章中,我们将深入分析Mapper接口的动态代理机制,并详细解答以上思考题,帮助大家更好地理解SqlSession在整个架构中的作用。</p>


</div>
<div id="MySignature" role="contentinfo">
    <p>本文来自博客园,作者:lunzi_fly,转载请注明原文链接:https://www.cnblogs.com/lunzi1992/p/19110480</p><br><br>
来源:https://www.cnblogs.com/lunzi1992/p/19110480
頁: [1]
查看完整版本: 【源码解读之 Mybatis】【基础篇】-- 第3篇:SqlSession的创建与生命周期