MyBatis 核心组件:SqlSession 全解析(创建、实现、线程安全与四大执行对象)
SqlSession 是 MyBatis 中连接开发者与底层数据库操作的核心接口,封装了数据库 CRUD、事务管理、缓存控制等核心能力。本文基于 SqlSession 接口定义、DefaultSqlSession 实现及 SqlSessionManager 源码,从 “接口定位→创建流程→实现逻辑→线程安全→底层协作” 五个维度,彻底拆解 SqlSession 的工作机制,同时关联 Executor 等四大核心对象,帮你掌握 MyBatis 会话管理的本质。
SqlSession 接口:MyBatis 会话的 “入口协议”
SqlSession 相当于 JDBC 中的 Connection,但功能更丰富 —— 不仅是数据库连接的封装,还提供了 Mapper 接口绑定、缓存管理、事务控制等能力。其接口定义按功能可分为 5 大类方法,覆盖所有数据库交互场景。
1. 核心方法分类与解析
(1)查询方法:select* 系列
查询方法是 SqlSession 最常用的功能,支持单结果、多结果、Map 结果、游标(Cursor)等多种返回形式,核心差异在于结果处理方式:
| 方法签名 |
功能说明 |
适用场景 |
<T> T selectOne(String statement) |
执行 SQL,返回单个结果(无参数) |
无参单结果查询(如 select count(*)) |
<T> T selectOne(String statement, Object param) |
执行 SQL,传入参数,返回单个结果 |
有参单结果查询(如 selectById(1)) |
<E> List<E> selectList(String statement) |
执行 SQL,返回结果列表(无参数) |
无参多结果查询(如 selectAll()) |
<E> List<E> selectList(..., RowBounds rb) |
传入 RowBounds(起始索引 + 条数),实现逻辑分页 |
逻辑分页查询(不推荐生产,见前文) |
<K,V> Map<K,V> selectMap(..., String mapKey) |
将结果列表转为 Map,mapKey 为 Map 的键(需是结果中的某个属性) |
需快速通过某个属性查找结果(如按 id 查 User) |
<T> Cursor<T> selectCursor(...) |
返回游标对象,支持流式读取(避免一次性加载大量数据到内存) |
大数据量查询(如导出 10 万条数据) |
void select(..., ResultHandler handler) |
无返回值,结果由自定义 ResultHandler 处理(灵活控制结果封装) |
特殊结果处理(如直接写入文件) |
关键细节:
selectOne() 本质是调用 selectList() 后取第一个元素,若结果集 size > 1 会抛出 TooManyResultsException;
RowBounds 实现逻辑分页(先查全表再截取),生产环境需用物理分页(如 PageHelper);
Cursor 是 MyBatis 3.4+ 新增功能,基于 JDBC 的 ResultSet 流式读取,适合大数据量场景,避免 OOM。
(2)修改方法:insert/update/delete
MyBatis 将 insert、update、delete 统一归为 “修改操作”,底层均委托给 Executor.update() 方法,返回值为受影响的行数: