【Mytais系列】Select语句执行流程

以下是通过 时序图文字说明 详细描述的 MyBatis 执行一条 SELECT 语句的完整流程,包括缓存查询、数据库访问和结果返回的各个环节:


时序图(Sequence Diagram)


详细执行流程解析

1. 客户端发起查询请求
  • 客户端调用 SqlSession 的查询方法(如 selectOne),传入 SQL 语句的标识(如 selectUserById)和参数(如 id=1)。
2. 二级缓存检查(CachingExecutor)
  • CachingExecutor 作为装饰器,优先检查 二级缓存(对应 Mapper 级别的缓存):
    • 若命中,直接返回缓存结果(流程结束)。
    • 若未命中,继续委托给底层 Executor(如 SimpleExecutorBatchExecutor)处理。
3. 一级缓存检查(BaseExecutor)
  • BaseExecutor 负责处理 一级缓存(当前 SqlSession 的缓存):
    • 若命中,返回缓存结果。
    • 若未命中,继续执行数据库查询。
4. 数据库查询
  • 4.1 创建 PreparedStatement
    StatementHandler 通过 Connection 创建 PreparedStatement 对象。
  • 4.2 参数绑定
    ParameterHandler 将参数(如 id=1)绑定到 SQL 中的占位符(?)。
  • 4.3 执行 SQL
    通过 JDBC 驱动执行 SQL,向数据库发送查询请求。
  • 4.4 结果映射
    ResultSetHandler 将返回的 ResultSet 转换为 Java 对象(如 User 对象)。
5. 缓存更新
  • 一级缓存更新
    查询结果立即存入当前 SqlSession 的一级缓存(localCache)。
  • 二级缓存更新
    SqlSession 执行了 commit()close(),且二级缓存已开启(<cache/> 配置),则结果会同步到二级缓存。
6. 结果返回
  • 最终结果通过 SqlSession 返回给客户端。

关键组件作用

组件

职责

SqlSession

用户操作 MyBatis 的入口,封装了会话状态和数据库操作。

Executor

执行器,负责缓存查询和 SQL 执行(分为 SimpleExecutorReuseExecutor 等)。

CachingExecutor

装饰器模式实现,添加二级缓存逻辑。

StatementHandler

处理 SQL 语句(创建 PreparedStatement)。

ParameterHandler

绑定 SQL 参数。

ResultSetHandler

处理结果集(映射为 Java 对象)。

JDBC Driver

实际执行数据库操作。


缓存与数据库访问的优先级

  1. 二级缓存(跨会话共享) → 2. 一级缓存(当前会话) → 3. 数据库
    • 若二级缓存未命中,但一级缓存命中,结果会直接返回,不会更新二级缓存
    • 二级缓存的更新需等待会话提交或关闭。

示例场景

场景 1:首次查询(无缓存)
// 1. 客户端发起查询
User user = sqlSession.selectOne("selectUserById", 1);

// 执行流程:
// 二级缓存未命中 → 一级缓存未命中 → 查询数据库 → 结果存入一级缓存
// 提交后同步到二级缓存
sqlSession.commit();
场景 2:同一会话重复查询
// 第一次查询(查数据库)
User user1 = sqlSession.selectOne("selectUserById", 1);

// 第二次查询(命中一级缓存)
User user2 = sqlSession.selectOne("selectUserById", 1);
场景 3:跨会话查询(二级缓存生效)
// Session1 查询并提交
SqlSession session1 = sqlSessionFactory.openSession();
User user1 = session1.selectOne("selectUserById", 1);
session1.commit();  // 同步到二级缓存
session1.close();

// Session2 查询(命中二级缓存)
SqlSession session2 = sqlSessionFactory.openSession();
User user2 = session2.selectOne("selectUserById", 1); 

注意事项

  1. 缓存一致性
    • 更新操作(INSERT/UPDATE/DELETE)会清空一级缓存(当前会话)和二级缓存(全局)。
  1. 事务提交
    • 未提交的会话中,二级缓存不会更新。
  1. 序列化要求
    • 二级缓存的对象需实现 Serializable 接口。
  1. 性能权衡
    • 高频写入场景下,建议关闭二级缓存,避免频繁缓存失效。

总结

MyBatis 的 SELECT 执行流程通过 二级缓存 → 一级缓存 → 数据库 的优先级策略,最大化利用缓存提升性能。理解其内部组件协作(如 ExecutorStatementHandler)和缓存更新机制,有助于优化数据访问层设计,平衡性能与数据一致性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值