MyBatis 工作流程详解
MyBatis 的工作流程分为 初始化阶段 和 运行时阶段(读/写操作),以下是详细步骤解析:
一、初始化阶段
目标:加载配置并构建 SqlSessionFactory。 流程:
-
解析全局配置(
mybatis-config.xml):- 加载数据源、事务管理器、插件、类型处理器等配置。
- 解析
<environments>确定数据库连接信息。
<!-- mybatis-config.xml --> <environments default="dev"> <environment id="dev"> <dataSource type="POOLED">...</dataSource> <transactionManager type="JDBC"/> </environment> </environments> -
解析 Mapper 文件:
- 扫描 XML 或注解定义的 SQL 语句,构建
MappedStatement对象(包含 SQL ID、参数映射、结果映射等)。
<!-- UserMapper.xml --> <mapper namespace="com.example.UserMapper"> <select id="selectUser" resultType="User"> SELECT * FROM user WHERE id = #{id} </select> </mapper> - 扫描 XML 或注解定义的 SQL 语句,构建
-
构建
SqlSessionFactory:- 将解析后的配置信息存入
Configuration对象,最终生成全局唯一的SqlSessionFactory。
- 将解析后的配置信息存入
二、运行时阶段(读操作)
目标:执行查询并返回结果。 流程:
-
创建
SqlSession:- 通过
SqlSessionFactory.openSession()创建会话(默认开启一级缓存)。
SqlSession session = sqlSessionFactory.openSession(); - 通过
-
获取 Mapper 代理对象:
- 通过动态代理生成
UserMapper接口的实现类。
UserMapper mapper = session.getMapper(UserMapper.class); - 通过动态代理生成
-
SQL 解析与参数绑定:
- 根据方法名
selectUser找到对应的MappedStatement。 - 解析动态 SQL(如
<if>标签),生成静态 SQL 并绑定参数。
- 根据方法名
-
执行 SQL:
- 执行器(Executor) 调用
StatementHandler创建PreparedStatement。 - 参数处理器(ParameterHandler) 将 Java 对象转换为 JDBC 参数。
// 伪代码:参数映射示例 pstmt.setInt(1, id); // 将 #{id} 替换为实际值 - 执行器(Executor) 调用
-
结果集映射:
- 结果集处理器(ResultSetHandler) 将
ResultSet转换为User对象(自动或通过ResultMap)。 - 若开启二级缓存,缓存结果。
- 结果集处理器(ResultSetHandler) 将
-
返回结果:
User user = mapper.selectUser(1);
三、运行时阶段(写操作)
目标:执行插入/更新/删除操作,管理事务。 流程:
-
开启事务:
- 默认情况下,
SqlSession不会自动提交事务(需手动调用commit())。
SqlSession session = sqlSessionFactory.openSession(); // 自动提交设为 false - 默认情况下,
-
执行写操作:
- 与读操作类似,通过执行器调用
update()方法。
int rows = mapper.updateUser(user); - 与读操作类似,通过执行器调用
-
事务提交/回滚:
- 成功时提交:
session.commit(); - 异常时回滚:
session.rollback();
- 成功时提交:
-
关闭会话:
session.close(); // 释放连接,清空一级缓存
四、核心流程图示
初始化阶段
解析mybatis-config.xml
解析Mapper XML/注解
构建SqlSessionFactory
运行时读操作
创建SqlSession
获取Mapper代理
解析SQL与参数
Executor执行SQL
ResultSet映射结果
运行时写操作
开启事务
执行更新操作
提交/回滚事务
五、关键机制
-
一级缓存:
- 作用范围:
SqlSession级别,相同查询直接返回缓存对象。 - 失效场景:执行更新操作或调用
clearCache()。
- 作用范围:
-
二级缓存:
- 作用范围:跨
SqlSession,需在 Mapper XML 中配置<cache/>。 - 序列化要求:实体类需实现
Serializable。
- 作用范围:跨
-
动态 SQL:
- 使用
<if>,<foreach>等标签生成动态条件,避免 SQL 注入。
- 使用
六、示例场景
批量插入优化:
try (SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
UserMapper mapper = session.getMapper(UserMapper.class);
for (User user : userList) {
mapper.insertUser(user); // 批量模式缓存 SQL,最后一次性提交
}
session.commit(); // 统一提交,减少数据库交互
}
总结
MyBatis 工作流程分为初始化(加载配置)和运行时(SQL 解析、执行、结果映射),通过 SqlSession 管理会话,Executor 控制执行策略,支持动态 SQL 和缓存机制,兼顾灵活性与性能,适合需精细控制 SQL 的场景。